static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg)
{
	struct hdhomerun_debug_t *dbg = (struct hdhomerun_debug_t *)arg;

	while (!dbg->terminate) {

		pthread_mutex_lock(&dbg->queue_lock);
		struct hdhomerun_debug_message_t *message = dbg->queue_tail;
		uint32_t queue_depth = dbg->queue_depth;
		pthread_mutex_unlock(&dbg->queue_lock);

		if (!message) {
			msleep_approx(250);
			continue;
		}

		if (queue_depth > 1024) {
			hdhomerun_debug_pop_and_free_message(dbg);
			continue;
		}

		if (!hdhomerun_debug_output_message(dbg, message)) {
			msleep_approx(250);
			continue;
		}

		hdhomerun_debug_pop_and_free_message(dbg);
	}

	return 0;
}
void msleep_minimum(uint64_t ms)
{
	uint64_t stop_time = getcurrenttime() + ms;

	while (1) {
		uint64_t current_time = getcurrenttime();
		if (current_time >= stop_time) {
			return;
		}

		msleep_approx(stop_time - current_time);
	}
}
void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout)
{
	if (!dbg) {
		return;
	}

	timeout = getcurrenttime() + timeout;

	while (getcurrenttime() < timeout) {
		pthread_mutex_lock(&dbg->queue_lock);
		struct hdhomerun_debug_message_t *message = dbg->queue_tail;
		pthread_mutex_unlock(&dbg->queue_lock);

		if (!message) {
			return;
		}

		msleep_approx(10);
	}
}
static int channelscan_find_lock(struct hdhomerun_channelscan_t *scan, uint32_t frequency, struct hdhomerun_channelscan_result_t *result)
{
	/* Set channel. */
	char channel_str[64];
	hdhomerun_sprintf(channel_str, channel_str + sizeof(channel_str), "auto:%u", (unsigned int)frequency);

	int ret = hdhomerun_device_set_tuner_channel(scan->hd, channel_str);
	if (ret <= 0) {
		return ret;
	}

	/* Wait for lock. */
	ret = hdhomerun_device_wait_for_lock(scan->hd, &result->status);
	if (ret <= 0) {
		return ret;
	}
	if (!result->status.lock_supported) {
		return 1;
	}

	/* Wait for symbol quality = 100%. */
	uint64_t timeout = getcurrenttime() + 5000;
	while (1) {
		ret = hdhomerun_device_get_tuner_status(scan->hd, NULL, &result->status);
		if (ret <= 0) {
			return ret;
		}

		if (result->status.symbol_error_quality == 100) {
			return 1;
		}

		if (getcurrenttime() >= timeout) {
			return 1;
		}

		msleep_approx(250);
	}
}
Beispiel #5
0
static bool_t hdhomerun_sock_wait_for_write_event(hdhomerun_sock_t sock, uint64_t stop_time)
{
	uint64_t current_time = getcurrenttime();
	if (current_time >= stop_time) {
		return FALSE;
	}

	if (sock < FD_SETSIZE) {
		uint64_t timeout = stop_time - current_time;
		struct timeval t;
		t.tv_sec = timeout / 1000;
		t.tv_usec = (timeout % 1000) * 1000;

		fd_set writefds;
		FD_ZERO(&writefds);
		FD_SET(sock, &writefds);

		fd_set errorfds;
		FD_ZERO(&errorfds);
		FD_SET(sock, &errorfds);

		if (select(sock + 1, NULL, &writefds, &errorfds, &t) <= 0) {
			return FALSE;
		}
		if (!FD_ISSET(sock, &writefds)) {
			return FALSE;
		}
	} else {
		uint64_t delay = stop_time - current_time;
		if (delay > 5) {
			delay = 5;
		}

		msleep_approx(delay);
	}

	return TRUE;
}
Beispiel #6
0
static int cmd_save(const char *tuner_str, const char *filename)
{
	if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) {
		fprintf(stderr, "invalid tuner number\n");
		return -1;
	}

	FILE *fp;
	if (strcmp(filename, "null") == 0) {
		fp = NULL;
	} else if (strcmp(filename, "-") == 0) {
		fp = stdout;
	} else {
		fp = fopen(filename, "wb");
		if (!fp) {
			fprintf(stderr, "unable to create file %s\n", filename);
			return -1;
		}
	}

	int ret = hdhomerun_device_stream_start(hd);
	if (ret <= 0) {
		fprintf(stderr, "unable to start stream\n");
		if (fp && fp != stdout) {
			fclose(fp);
		}
		return ret;
	}

	register_signal_handlers(sigabort_handler, sigabort_handler, siginfo_handler);

	struct hdhomerun_video_stats_t stats_old, stats_cur;
	hdhomerun_device_get_video_stats(hd, &stats_old);

	uint64_t next_progress = getcurrenttime() + 1000;

	while (!sigabort_flag) {
		uint64_t loop_start_time = getcurrenttime();

		if (siginfo_flag) {
			fprintf(stderr, "\n");
			cmd_save_print_stats();
			siginfo_flag = FALSE;
		}

		size_t actual_size;
		uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size);
		if (!ptr) {
			msleep_approx(64);
			continue;
		}

		if (fp) {
			if (fwrite(ptr, 1, actual_size, fp) != actual_size) {
				fprintf(stderr, "error writing output\n");
				return -1;
			}
		}

		if (loop_start_time >= next_progress) {
			next_progress += 1000;
			if (loop_start_time >= next_progress) {
				next_progress = loop_start_time + 1000;
			}

			/* Windows - indicate activity to suppress auto sleep mode. */
			#if defined(__WINDOWS__)
			SetThreadExecutionState(ES_SYSTEM_REQUIRED);
			#endif

			/* Video stats. */
			hdhomerun_device_get_video_stats(hd, &stats_cur);

			if (stats_cur.overflow_error_count > stats_old.overflow_error_count) {
				fprintf(stderr, "o");
			} else if (stats_cur.network_error_count > stats_old.network_error_count) {
				fprintf(stderr, "n");
			} else if (stats_cur.transport_error_count > stats_old.transport_error_count) {
				fprintf(stderr, "t");
			} else if (stats_cur.sequence_error_count > stats_old.sequence_error_count) {
				fprintf(stderr, "s");
			} else {
				fprintf(stderr, ".");
			}

			stats_old = stats_cur;
			fflush(stderr);
		}

		int32_t delay = 64 - (int32_t)(getcurrenttime() - loop_start_time);
		if (delay <= 0) {
			continue;
		}

		msleep_approx(delay);
	}

	if (fp) {
		fclose(fp);
	}

	hdhomerun_device_stream_stop(hd);

	fprintf(stderr, "\n");
	fprintf(stderr, "-- Video statistics --\n");
	cmd_save_print_stats();

	return 0;
}
int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result)
{
	scan->scanned_channels++;

	/* Find lock. */
	int ret = channelscan_find_lock(scan, result->frequency, result);
	if (ret <= 0) {
		return ret;
	}
	if (!result->status.lock_supported) {
		return 1;
	}

	/* Detect programs. */
	result->program_count = 0;

	uint64_t timeout;
	if (strstr(hdhomerun_device_get_model_str(scan->hd), "atsc")) {
		timeout = getcurrenttime() + 4000;
	} else {
		timeout = getcurrenttime() + 10000;
	}

	uint64_t complete_time = getcurrenttime() + 1000;

	while (1) {
		bool_t changed, incomplete;
		ret = channelscan_detect_programs(scan, result, &changed, &incomplete);
		if (ret <= 0) {
			return ret;
		}

		if (changed) {
			complete_time = getcurrenttime() + 1000;
		}

		if (!incomplete && (getcurrenttime() >= complete_time)) {
			break;
		}

		if (getcurrenttime() >= timeout) {
			break;
		}

		msleep_approx(250);
	}

	/* Lock => skip overlapping channels. */
	uint32_t max_next_frequency = result->frequency - 5500000;
	while (1) {
		if (!scan->next_channel) {
			break;
		}

		if (hdhomerun_channel_entry_frequency(scan->next_channel) <= max_next_frequency) {
			break;
		}

		scan->next_channel = hdhomerun_channel_list_prev(scan->channel_list, scan->next_channel);
	}

	/* Success. */
	return 1;
}