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; }
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; }
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; }
/** \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(); }
/** \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); }
/** \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(); }