diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythhdhomerun/hdhomerun_video.c myth.20207.0313b/mythtv/libs/libmythhdhomerun/hdhomerun_video.c
|
|
|
49 | 49 | volatile uint32_t network_error_count; |
50 | 50 | volatile uint32_t sequence_error_count; |
51 | 51 | volatile uint32_t overflow_error_count; |
| 52 | volatile uint32_t buffer_highwater_mark; |
52 | 53 | volatile uint8_t sequence[0x2000]; |
53 | 54 | }; |
54 | 55 | |
… |
… |
|
286 | 287 | head -= vs->buffer_size; |
287 | 288 | } |
288 | 289 | |
| 290 | /* update buffer_highwater_mark */ |
| 291 | /* head - where things will be inserted */ |
| 292 | /* tail - where things will be removed */ |
| 293 | size_t tail = vs->tail; |
| 294 | uint32_t space_used; |
| 295 | if (head > tail) { |
| 296 | space_used = head - tail; |
| 297 | } else { |
| 298 | /* head < tail */ |
| 299 | space_used = (head + vs->buffer_size) - tail; |
| 300 | } |
| 301 | |
| 302 | if (space_used > vs->buffer_highwater_mark) { |
| 303 | vs->buffer_highwater_mark = space_used; |
| 304 | } |
| 305 | |
289 | 306 | /* Check for buffer overflow. */ |
290 | 307 | if (head == vs->tail) { |
291 | 308 | vs->overflow_error_count++; |
… |
… |
|
367 | 384 | vs->network_error_count = 0; |
368 | 385 | vs->sequence_error_count = 0; |
369 | 386 | vs->overflow_error_count = 0; |
| 387 | vs->buffer_highwater_mark = 0; |
370 | 388 | |
371 | 389 | pthread_mutex_unlock(&vs->lock); |
372 | 390 | } |
… |
… |
|
376 | 394 | struct hdhomerun_video_stats_t stats; |
377 | 395 | hdhomerun_video_get_stats(vs, &stats); |
378 | 396 | |
379 | | hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n", |
| 397 | hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld hwm=%ld\n", |
380 | 398 | stats.packet_count, stats.network_error_count, |
381 | 399 | stats.transport_error_count, stats.sequence_error_count, |
382 | | stats.overflow_error_count |
| 400 | stats.overflow_error_count, stats.buffer_highwater_mark |
383 | 401 | ); |
384 | 402 | } |
385 | 403 | |
… |
… |
|
394 | 412 | stats->transport_error_count = vs->transport_error_count; |
395 | 413 | stats->sequence_error_count = vs->sequence_error_count; |
396 | 414 | stats->overflow_error_count = vs->overflow_error_count; |
| 415 | stats->buffer_highwater_mark = vs->buffer_highwater_mark; |
397 | 416 | |
398 | 417 | pthread_mutex_unlock(&vs->lock); |
399 | 418 | } |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythhdhomerun/hdhomerun_video.h myth.20207.0313b/mythtv/libs/libmythhdhomerun/hdhomerun_video.h
|
|
|
41 | 41 | uint32_t transport_error_count; |
42 | 42 | uint32_t sequence_error_count; |
43 | 43 | uint32_t overflow_error_count; |
| 44 | uint32_t buffer_highwater_mark; |
44 | 45 | }; |
45 | 46 | |
46 | 47 | #define TS_PACKET_SIZE 188 |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/DeviceReadBuffer.cpp myth.20207.0313b/mythtv/libs/libmythtv/DeviceReadBuffer.cpp
|
|
|
214 | 214 | used += len; |
215 | 215 | writePtr += len; |
216 | 216 | writePtr = (writePtr == endPtr) ? buffer : writePtr; |
217 | | #if REPORT_RING_STATS |
218 | 217 | max_used = max(used, max_used); |
| 218 | #if REPORT_RING_STATS |
219 | 219 | avg_used = ((avg_used * avg_cnt) + used) / ++avg_cnt; |
220 | 220 | #endif |
221 | 221 | } |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/DeviceReadBuffer.h myth.20207.0313b/mythtv/libs/libmythtv/DeviceReadBuffer.h
|
|
|
40 | 40 | void Reset(const QString &streamName, int streamfd); |
41 | 41 | void Stop(void); |
42 | 42 | |
| 43 | size_t GetMaxUsed() const { return max_used; }; |
| 44 | |
43 | 45 | void SetRequestPause(bool request); |
44 | 46 | bool IsPaused(void) const; |
45 | 47 | bool WaitForUnpause(unsigned long timeout); |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/ThreadedFileWriter.cpp myth.20207.0313b/mythtv/libs/libmythtv/ThreadedFileWriter.cpp
|
|
|
134 | 134 | rpos(0), wpos(0), |
135 | 135 | written(0), |
136 | 136 | // buffer |
137 | | buf(NULL), tfw_buf_size(0) |
| 137 | buf(NULL), tfw_buf_size(0), |
| 138 | tfw_highwater_mark(0) |
138 | 139 | { |
139 | 140 | filename.detach(); |
140 | 141 | } |
… |
… |
|
168 | 169 | |
169 | 170 | tfw_buf_size = TFW_DEF_BUF_SIZE; |
170 | 171 | tfw_min_write_size = TFW_MIN_WRITE_SIZE; |
| 172 | tfw_highwater_mark = 0; |
171 | 173 | pthread_create(&writer, NULL, boot_writer, this); |
172 | 174 | pthread_create(&syncer, NULL, boot_syncer, this); |
173 | 175 | return true; |
… |
… |
|
200 | 202 | delete [] buf; |
201 | 203 | buf = NULL; |
202 | 204 | } |
| 205 | |
| 206 | VERBOSE(VB_GENERAL, LOC + QString("Buffer size = %1 KB hwm = %2 KB") |
| 207 | .arg(tfw_buf_size / 1024).arg(tfw_highwater_mark/1024)); |
203 | 208 | } |
204 | 209 | |
205 | 210 | /** \fn ThreadedFileWriter::Write(const void*, uint) |
… |
… |
|
511 | 516 | /** \fn ThreadedFileWriter::BufUsed(void) const |
512 | 517 | * \brief Number of bytes queued for write by the write thread. With locking. |
513 | 518 | */ |
514 | | uint ThreadedFileWriter::BufUsed(void) const |
| 519 | uint ThreadedFileWriter::BufUsed(void) |
515 | 520 | { |
516 | 521 | QMutexLocker locker(&buflock); |
517 | | return (wpos >= rpos) ? wpos - rpos : tfw_buf_size - rpos + wpos; |
| 522 | uint result = (wpos >= rpos) ? wpos - rpos : tfw_buf_size - rpos + wpos; |
| 523 | if (result > tfw_highwater_mark) |
| 524 | tfw_highwater_mark=result; |
| 525 | return result; |
518 | 526 | } |
519 | 527 | |
520 | 528 | /** |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/ThreadedFileWriter.h myth.20207.0313b/mythtv/libs/libmythtv/ThreadedFileWriter.h
|
|
|
21 | 21 | void SetWriteBufferSize(uint newSize = TFW_DEF_BUF_SIZE); |
22 | 22 | void SetWriteBufferMinWriteSize(uint newMinSize = TFW_MIN_WRITE_SIZE); |
23 | 23 | |
24 | | uint BufUsed(void) const; |
| 24 | uint BufUsed(void); |
25 | 25 | uint BufFree(void) const; |
26 | 26 | |
27 | 27 | void Sync(void); |
… |
… |
|
61 | 61 | // buffer |
62 | 62 | char *buf; |
63 | 63 | unsigned long tfw_buf_size; |
| 64 | unsigned long tfw_highwater_mark; |
64 | 65 | |
65 | 66 | // threads |
66 | 67 | pthread_t writer; |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/dvbrecorder.cpp myth.20207.0313b/mythtv/libs/libmythtv/dvbrecorder.cpp
|
|
|
330 | 330 | { |
331 | 331 | VERBOSE(VB_RECORD, LOC + "Close() fd("<<_stream_fd<<") -- begin"); |
332 | 332 | |
| 333 | uint hwm = _stream_handler->GetMaxUsed(); |
| 334 | VERBOSE(VB_GENERAL,QString( LOC + "DVB Stats: pkts=%1 hwm=%2 KB Errors: trnsprt=%3 seq=%4") |
| 335 | .arg(_total_packet_count) |
| 336 | .arg(hwm/1024) |
| 337 | .arg(_transport_error_count) |
| 338 | .arg(_continuity_error_count)); |
| 339 | |
333 | 340 | DVBStreamHandler::Return(_stream_handler); |
334 | 341 | |
335 | 342 | VERBOSE(VB_RECORD, LOC + "Close() fd("<<_stream_fd<<") -- end"); |
… |
… |
|
374 | 381 | |
375 | 382 | _continuity_error_count = 0; |
376 | 383 | _stream_overflow_count = 0; |
| 384 | _transport_error_count = 0; |
| 385 | _bad_packet_count = 0; |
| 386 | _total_packet_count = 0; |
377 | 387 | |
378 | 388 | _request_recording = true; |
379 | 389 | _recording = true; |
… |
… |
|
519 | 529 | QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); |
520 | 530 | _continuity_error_count++; |
521 | 531 | } |
| 532 | if (tspacket.TransportError()) |
| 533 | { |
| 534 | _transport_error_count++; |
| 535 | } |
| 536 | _total_packet_count++; |
522 | 537 | |
523 | 538 | // Sync recording start to first keyframe |
524 | 539 | if (_wait_for_keyframe_option && _first_keyframe < 0) |
… |
… |
|
553 | 568 | QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); |
554 | 569 | _continuity_error_count++; |
555 | 570 | } |
| 571 | if (tspacket.TransportError()) |
| 572 | { |
| 573 | _transport_error_count++; |
| 574 | } |
| 575 | |
| 576 | _total_packet_count++; |
556 | 577 | |
557 | 578 | // Only create fake keyframe[s] if there are no audio/video streams |
558 | 579 | if (_input_pmt && _has_no_av) |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/dvbrecorder.h myth.20207.0313b/mythtv/libs/libmythtv/dvbrecorder.h
|
|
|
125 | 125 | mutable uint _continuity_error_count; |
126 | 126 | mutable uint _stream_overflow_count; |
127 | 127 | mutable uint _bad_packet_count; |
| 128 | mutable uint _transport_error_count; |
| 129 | mutable uint _total_packet_count; |
128 | 130 | |
129 | 131 | // Constants |
130 | 132 | static const int TSPACKETS_BETWEEN_PSIP_SYNC; |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/dvbstreamhandler.cpp myth.20207.0313b/mythtv/libs/libmythtv/dvbstreamhandler.cpp
|
|
|
98 | 98 | |
99 | 99 | _pid_lock(QMutex::Recursive), |
100 | 100 | _open_pid_filters(0), |
101 | | _listener_lock(QMutex::Recursive) |
| 101 | _listener_lock(QMutex::Recursive), |
| 102 | _max_used(0) |
102 | 103 | { |
103 | 104 | } |
104 | 105 | |
… |
… |
|
208 | 209 | } |
209 | 210 | } |
210 | 211 | |
| 212 | uint DVBStreamHandler::GetMaxUsed(void) |
| 213 | { |
| 214 | QMutexLocker locker(&_start_stop_lock); |
| 215 | if (_device_read_buffer) |
| 216 | { |
| 217 | _max_used = _device_read_buffer->GetMaxUsed(); |
| 218 | } |
| 219 | return _max_used; |
| 220 | } |
| 221 | |
211 | 222 | void DVBStreamHandler::Stop(void) |
212 | 223 | { |
213 | 224 | QMutexLocker locker(&_start_stop_lock); |
… |
… |
|
215 | 226 | if (IsRunning()) |
216 | 227 | { |
217 | 228 | if (_device_read_buffer) |
| 229 | { |
218 | 230 | _device_read_buffer->Stop(); |
| 231 | _max_used = _device_read_buffer->GetMaxUsed(); |
| 232 | } |
219 | 233 | SetRunning(false); |
220 | 234 | pthread_join(_reader_thread, NULL); |
221 | 235 | } |
… |
… |
|
255 | 269 | return; |
256 | 270 | bzero(buffer, buffer_size); |
257 | 271 | |
| 272 | VERBOSE(VB_GENERAL, QString(LOC + "HD Ringbuffer size = %1 KB").arg(buffer_size / 1024)); |
| 273 | |
258 | 274 | QByteArray dvr_dev_path = _dvr_dev_path.toAscii(); |
259 | 275 | int dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK); |
260 | 276 | if (dvr_fd < 0) |
… |
… |
|
369 | 385 | if (_device_read_buffer->IsRunning()) |
370 | 386 | _device_read_buffer->Stop(); |
371 | 387 | |
| 388 | _max_used=_device_read_buffer->GetMaxUsed(); |
| 389 | |
372 | 390 | delete _device_read_buffer; |
373 | 391 | _device_read_buffer = NULL; |
374 | 392 | } |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/dvbstreamhandler.h myth.20207.0313b/mythtv/libs/libmythtv/dvbstreamhandler.h
|
|
|
70 | 70 | // ReaderPausedCB |
71 | 71 | virtual void ReaderPaused(int fd) { (void) fd; } |
72 | 72 | |
| 73 | uint GetMaxUsed(); |
| 74 | |
73 | 75 | private: |
74 | 76 | DVBStreamHandler(const QString &); |
75 | 77 | ~DVBStreamHandler(); |
… |
… |
|
118 | 120 | mutable QMutex _listener_lock; |
119 | 121 | vector<MPEGStreamData*> _stream_data_list; |
120 | 122 | |
| 123 | uint _max_used; |
| 124 | |
121 | 125 | // for caching TS monitoring supported value. |
122 | 126 | static QMutex _rec_supports_ts_monitoring_lock; |
123 | 127 | static QMap<QString,bool> _rec_supports_ts_monitoring; |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/hdhrrecorder.cpp myth.20207.0313b/mythtv/libs/libmythtv/hdhrrecorder.cpp
|
|
|
117 | 117 | memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); |
118 | 118 | |
119 | 119 | _stream_handler = HDHRStreamHandler::Get(_channel->GetDevice()); |
| 120 | _stream_handler->GetStats(&_start_stats, false); |
120 | 121 | |
121 | 122 | VERBOSE(VB_RECORD, LOC + "HDHR opened successfully"); |
122 | 123 | |
… |
… |
|
129 | 130 | |
130 | 131 | if (IsOpen()) |
131 | 132 | { |
| 133 | hdhomerun_video_stats_t end_stats; |
| 134 | _stream_handler->GetStats(&end_stats, true); |
| 135 | |
| 136 | VERBOSE(VB_GENERAL,QString( LOC + "HDHR Stats: pkts=%1 hwm=%6 KB Errors: net=%2 trnsprt=%3 seq=%4 ovflow=%5") |
| 137 | .arg(end_stats.packet_count - _start_stats.packet_count) |
| 138 | .arg(end_stats.network_error_count - _start_stats.network_error_count) |
| 139 | .arg(end_stats.transport_error_count - _start_stats.transport_error_count) |
| 140 | .arg(end_stats.sequence_error_count - _start_stats.sequence_error_count) |
| 141 | .arg(end_stats.overflow_error_count - _start_stats.overflow_error_count) |
| 142 | .arg(end_stats.buffer_highwater_mark / 1024)); /* buffer_highwater_mark is absolute */ |
| 143 | |
132 | 144 | HDHRStreamHandler::Return(_stream_handler); |
133 | 145 | } |
134 | 146 | |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/hdhrrecorder.h myth.20207.0313b/mythtv/libs/libmythtv/hdhrrecorder.h
|
|
|
95 | 95 | ProgramMapTable *_input_pmt; |
96 | 96 | bool _has_no_av; |
97 | 97 | |
| 98 | hdhomerun_video_stats_t _start_stats; |
| 99 | |
98 | 100 | unsigned char _stream_id[0x1fff]; |
99 | 101 | unsigned char _pid_status[0x1fff]; |
100 | 102 | unsigned char _continuity_counter[0x1fff]; |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/hdhrstreamhandler.cpp myth.20207.0313b/mythtv/libs/libmythtv/hdhrstreamhandler.cpp
|
|
|
112 | 112 | _listener_lock(QMutex::Recursive), |
113 | 113 | _hdhr_lock(QMutex::Recursive) |
114 | 114 | { |
| 115 | memset(&_last_stats, 0, sizeof(_last_stats)); |
115 | 116 | } |
116 | 117 | |
117 | 118 | HDHRStreamHandler::~HDHRStreamHandler() |
… |
… |
|
294 | 295 | return (QString::null != TunerSet("target", "0.0.0.0:0")); |
295 | 296 | } |
296 | 297 | |
| 298 | void HDHRStreamHandler::GetStats(hdhomerun_video_stats_t* stats, bool use_cache) { |
| 299 | QMutexLocker locker(&_hdhr_lock); |
| 300 | if (_video_socket) { |
| 301 | hdhomerun_video_get_stats(_video_socket, &_last_stats); |
| 302 | memcpy(stats, &_last_stats, sizeof(hdhomerun_video_stats_t)); |
| 303 | } else if (use_cache) { |
| 304 | memcpy(stats, &_last_stats, sizeof(hdhomerun_video_stats_t)); |
| 305 | } else { |
| 306 | memset(stats, 0, sizeof(hdhomerun_video_stats_t)); |
| 307 | } |
| 308 | } |
| 309 | |
297 | 310 | QString HDHRStreamHandler::GetTunerStatus() { |
298 | 311 | return TunerGet("status"); |
299 | 312 | } |
… |
… |
|
511 | 524 | hdhomerun_video_sock_t* tmp_video_socket; |
512 | 525 | { |
513 | 526 | QMutexLocker locker(&_hdhr_lock); |
| 527 | hdhomerun_video_get_stats(_video_socket, &_last_stats); |
514 | 528 | tmp_video_socket = _video_socket; |
515 | 529 | _video_socket=NULL; |
516 | 530 | } |
diff -r -u -N -X diff.exclude -x myth.20207.0313a -x myth.20207.0313b myth.20207.0313a/mythtv/libs/libmythtv/hdhrstreamhandler.h myth.20207.0313b/mythtv/libs/libmythtv/hdhrstreamhandler.h
|
|
|
50 | 50 | DTVSignalMonitor *sigmon, |
51 | 51 | HDHRChannel *dvbchan); |
52 | 52 | |
| 53 | void GetStats(hdhomerun_video_stats_t* stats, bool use_cache); |
| 54 | |
53 | 55 | // ReaderPausedCB |
54 | 56 | virtual void ReaderPaused(int fd) { (void) fd; } |
55 | 57 | |
… |
… |
|
106 | 108 | private: |
107 | 109 | hdhomerun_control_sock_t *_control_socket; |
108 | 110 | hdhomerun_video_sock_t *_video_socket; |
| 111 | hdhomerun_video_stats_t _last_stats; |
109 | 112 | uint _device_id; |
110 | 113 | uint _device_ip; |
111 | 114 | uint _tuner; |