PyObject *py_device_stream_start(py_device_object *self) {
    int success;

    success = hdhomerun_device_stream_start(self->hd);
    if(success == -1) {
        PyErr_SetString(PyExc_IOError, DEVICE_ERR_COMMUNICATION);
        return NULL;
    } else if(success == 0) {
        PyErr_SetString(hdhomerun_device_error, "the device refused to start streaming");
        return NULL;
    } else if(success != 1) {
        PyErr_SetString(hdhomerun_device_error, DEVICE_ERR_UNDOCUMENTED);
        return NULL;
    }
    Py_RETURN_NONE;
}
Beispiel #2
0
void HDHRDevice::captureThread()
{
	unsigned char *buf = NULL;
	int result;
	
	if(!mChannel) return;
	if(!mDeviceConnection) return;
	
	mCaptureThread = pthread_self();
	mCaptureThreadRunning = true;
	
//	flog( "Native.log",  "HDHomeRun: native capture thread starting\r\n");
	
	// start the device
	result = hdhomerun_device_stream_start(mDeviceConnection);
	if(result <= 0) {
		flog( "Native.log",  "HDHomeRun: Error starting stream\r\n");
		return;
	}
	
	while(!mKillCaptureThread) {
		size_t actual_size;
		
		// every 64ms read data from the hdhr device and push it to mChannel
		usleep(64000);
		
		buf = hdhomerun_device_stream_recv(mDeviceConnection, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size);
		if(!buf) continue;
		
		mChannel->pushData(buf, actual_size);
	}
	hdhomerun_device_stream_flush(mDeviceConnection);
	hdhomerun_device_stream_stop(mDeviceConnection);
	
	mCaptureThreadRunning = false;
}
Beispiel #3
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;
}
Beispiel #4
0
/** \fn HDHRStreamHandler::run(void)
 *  \brief Reads HDHomeRun socket for tables & data
 */
void HDHRStreamHandler::run(void)
{
    RunProlog();
    /* Create TS socket. */
    if (!hdhomerun_device_stream_start(_hdhomerun_device))
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "Starting recording (set target failed). Aborting.");
        _error = true;
        RunEpilog();
        return;
    }
    hdhomerun_device_stream_flush(_hdhomerun_device);

    SetRunning(true, false, false);

    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin");

    int remainder = 0;
    QTime last_update;
    while (_running_desired && !_error)
    {
        int elapsed = !last_update.isValid() ? -1 : last_update.elapsed();
        elapsed = (elapsed < 0) ? 1000 : elapsed;
        if (elapsed > 100)
        {
            UpdateFiltersFromStreamData();
            if (_tune_mode != hdhrTuneModeVChannel)
                UpdateFilters();
            last_update.restart();
        }

        size_t read_size = 64 * 1024; // read about 64KB
        read_size /= VIDEO_DATA_PACKET_SIZE;
        read_size *= VIDEO_DATA_PACKET_SIZE;

        size_t data_length;
        unsigned char *data_buffer = hdhomerun_device_stream_recv(
            _hdhomerun_device, read_size, &data_length);

        if (!data_buffer)
        {
            usleep(20000);
            continue;
        }

        // Assume data_length is a multiple of 188 (packet size)

        _listener_lock.lock();

        if (_stream_data_list.empty())
        {
            _listener_lock.unlock();
            continue;
        }

        StreamDataList::const_iterator sit = _stream_data_list.begin();
        for (; sit != _stream_data_list.end(); ++sit)
            remainder = sit.key()->ProcessData(data_buffer, data_length);

        _listener_lock.unlock();
        if (remainder != 0)
        {
            LOG(VB_RECORD, LOG_INFO, LOC +
                QString("RunTS(): data_length = %1 remainder = %2")
                    .arg(data_length).arg(remainder));
        }
    }
    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown");

    RemoveAllPIDFilters();

    hdhomerun_device_stream_stop(_hdhomerun_device);
    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end");

    SetRunning(false, false, false);
    RunEpilog();
}
Beispiel #5
0
/** \fn HDHRStreamHandler::RunTS(void)
 *  \brief Uses TS filtering devices to read a DVB device for tables & data
 *
 *  This supports all types of MPEG based stream data, but is extreemely
 *  slow with DVB over USB 1.0 devices which for efficiency reasons buffer
 *  a stream until a full block transfer buffer full of the requested
 *  tables is available. This takes a very long time when you are just
 *  waiting for a PAT or PMT table, and the buffer is hundreds of packets
 *  in size.
 */
void HDHRStreamHandler::RunTS(void)
{
    int remainder = 0;

    /* Calculate buffer size */
    uint buffersize = gCoreContext->GetNumSetting(
        "HDRingbufferSize", 50 * TSPacket::SIZE) * 1024;
    buffersize /= VIDEO_DATA_PACKET_SIZE;
    buffersize *= VIDEO_DATA_PACKET_SIZE;

    // Buffer should be at least about 1MB..
    buffersize = max(49 * TSPacket::SIZE * 128, buffersize);

    /* Create TS socket. */
    if (!hdhomerun_device_stream_start(_hdhomerun_device))
    {
        VERBOSE(VB_IMPORTANT, LOC_ERR +
                "Starting recording (set target failed). Aborting.");
        return;
    }
    hdhomerun_device_stream_flush(_hdhomerun_device);

    bool _error = false;

    VERBOSE(VB_RECORD, LOC + "RunTS(): begin");

    while (IsRunning() && !_error)
    {
        UpdateFiltersFromStreamData();

        size_t read_size = 64 * 1024; // read about 64KB
        read_size /= VIDEO_DATA_PACKET_SIZE;
        read_size *= VIDEO_DATA_PACKET_SIZE;

        size_t data_length;
        unsigned char *data_buffer = hdhomerun_device_stream_recv(
            _hdhomerun_device, read_size, &data_length);

        if (!data_buffer)
        {
            usleep(5000);
            continue;
        }

        // Assume data_length is a multiple of 188 (packet size)

        _listener_lock.lock();

        if (_stream_data_list.empty())
        {
            _listener_lock.unlock();
            continue;
        }

        for (uint i = 0; i < _stream_data_list.size(); i++)
        {
            remainder = _stream_data_list[i]->ProcessData(
                data_buffer, data_length);
        }

        _listener_lock.unlock();
        if (remainder != 0)
        {
            VERBOSE(VB_RECORD, LOC +
                    QString("RunTS(): data_length = %1 remainder = %2")
                    .arg(data_length).arg(remainder));
        }
    }
    VERBOSE(VB_RECORD, LOC + "RunTS(): " + "shutdown");

    RemoveAllPIDFilters();

    hdhomerun_device_stream_stop(_hdhomerun_device);
    VERBOSE(VB_RECORD, LOC + "RunTS(): " + "end");

    SetRunning(false);
}
Beispiel #6
0
/** \fn HDHRStreamHandler::run(void)
 *  \brief Reads HDHomeRun socket for tables & data
 */
void HDHRStreamHandler::run(void)
{
    threadRegister("HDHRStreamHandler");
    /* Create TS socket. */
    if (!hdhomerun_device_stream_start(_hdhomerun_device))
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "Starting recording (set target failed). Aborting.");
        _error = true;
	threadDeregister();
        return;
    }
    hdhomerun_device_stream_flush(_hdhomerun_device);

    SetRunning(true, false, false);

    /* Calculate buffer size */
    uint buffersize = gCoreContext->GetNumSetting(
        "HDRingbufferSize", 50 * TSPacket::kSize) * 1024;
    buffersize /= VIDEO_DATA_PACKET_SIZE;
    buffersize *= VIDEO_DATA_PACKET_SIZE;
    buffersize = max(49 * TSPacket::kSize * 128, buffersize);

    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin");

    int remainder = 0;
    while (_running_desired && !_error)
    {
        UpdateFiltersFromStreamData();
        UpdateFilters();

        size_t read_size = 64 * 1024; // read about 64KB
        read_size /= VIDEO_DATA_PACKET_SIZE;
        read_size *= VIDEO_DATA_PACKET_SIZE;

        size_t data_length;
        unsigned char *data_buffer = hdhomerun_device_stream_recv(
            _hdhomerun_device, read_size, &data_length);

        if (!data_buffer)
        {
            usleep(5000);
            continue;
        }

        // Assume data_length is a multiple of 188 (packet size)

        _listener_lock.lock();

        if (_stream_data_list.empty())
        {
            _listener_lock.unlock();
            continue;
        }

        StreamDataList::const_iterator sit = _stream_data_list.begin();
        for (; sit != _stream_data_list.end(); ++sit)
            remainder = sit.key()->ProcessData(data_buffer, data_length);

        _listener_lock.unlock();
        if (remainder != 0)
        {
            LOG(VB_RECORD, LOG_INFO, LOC +
                QString("RunTS(): data_length = %1 remainder = %2")
                    .arg(data_length).arg(remainder));
        }
    }
    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown");

    RemoveAllPIDFilters();

    hdhomerun_device_stream_stop(_hdhomerun_device);
    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end");

    SetRunning(false, false, false);
    threadDeregister();
}