MythTV master
firewirerecorder.cpp
Go to the documentation of this file.
1
7// MythTV includes
9
10#include "firewirechannel.h"
11#include "firewirerecorder.h"
12#include "mpeg/mpegstreamdata.h"
13#include "mpeg/mpegtables.h"
14#include "tv_rec.h"
15
16#define LOC QString("FireRecBase[%1](%2): ") \
17 .arg(m_tvrec ? m_tvrec->GetInputId() : -1) \
18 .arg(m_channel->GetDevice())
19
21 DTVRecorder(rec),
22 m_channel(chan)
23{
24}
25
27{
28 Close();
29}
30
32{
33 if (!m_isopen)
34 {
37 }
38 return m_isopen;
39}
40
42{
43 if (m_isopen)
44 {
46 m_isopen = false;
47 }
48}
49
51{
53}
54
56{
58}
59
61{
62 LOG(VB_RECORD, LOG_INFO, LOC + "run");
63
64 if (!Open())
65 {
66 m_error = "Failed to open firewire device";
67 LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
68 return;
69 }
70
71 {
72 QMutexLocker locker(&m_pauseLock);
73 m_requestRecording = true;
74 m_recording = true;
75 m_recordingWait.wakeAll();
76 }
77
79
80 while (IsRecordingRequested() && !IsErrored())
81 {
82 if (PauseAndWait())
83 continue;
84
86 break;
87
88 { // sleep 1 seconds unless StopRecording() or Unpause() is called,
89 // just to avoid running this too often.
90 QMutexLocker locker(&m_pauseLock);
92 continue;
93 m_unpauseWait.wait(&m_pauseLock, 1000);
94 }
95 }
96
99
100 QMutexLocker locker(&m_pauseLock);
101 m_recording = false;
102 m_recordingWait.wakeAll();
103}
104
105void FirewireRecorder::AddData(const unsigned char *data, uint len)
106{
107 uint bufsz = m_buffer.size();
108 if ((SYNC_BYTE == data[0]) && (TSPacket::kSize == len) &&
109 (TSPacket::kSize > bufsz))
110 {
111 if (bufsz)
112 m_buffer.clear();
113
114 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
115 return;
116 }
117
118 m_buffer.insert(m_buffer.end(), data, data + len);
119 bufsz += len;
120
121 int sync_at = -1;
122 for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
123 {
124 if (m_buffer[i] == SYNC_BYTE)
125 sync_at = i;
126 }
127
128 if (sync_at < 0)
129 return;
130
131 if (bufsz < 30 * TSPacket::kSize)
132 return; // build up a little buffer
133
134 while (sync_at + TSPacket::kSize < bufsz)
135 {
136 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
137 (m_buffer).data() + sync_at)));
138
139 sync_at += TSPacket::kSize;
140 }
141
142 m_buffer.erase(m_buffer.begin(), m_buffer.begin() + sync_at);
143}
144
146{
147 const uint pid = tspacket.PID();
148
149 if (pid == 0x1fff) // Stuffing
150 return true;
151
152 if (tspacket.TransportError())
153 return true;
154
155 if (tspacket.Scrambled())
156 return true;
157
158 if (tspacket.HasAdaptationField())
160
161 if (GetStreamData()->IsVideoPID(tspacket.PID()))
162 return ProcessVideoTSPacket(tspacket);
163
164 if (GetStreamData()->IsAudioPID(tspacket.PID()))
165 return ProcessAudioTSPacket(tspacket);
166
167 if (GetStreamData()->IsWritingPID(tspacket.PID()))
168 BufferedWrite(tspacket);
169
170 if (GetStreamData()->IsListeningPID(tspacket.PID()) && tspacket.HasPayload())
171 GetStreamData()->HandleTSTables(&tspacket);
172
173 return true;
174}
175
176// documented in recorderbase.cpp
177bool FirewireRecorder::PauseAndWait(std::chrono::milliseconds timeout)
178{
179 QMutexLocker locker(&m_pauseLock);
180 if (m_requestPause)
181 {
182 LOG(VB_RECORD, LOG_INFO, LOC +
183 QString("PauseAndWait(%1) -- pause").arg(timeout.count()));
184 if (!IsPaused(true))
185 {
187 m_paused = true;
188 m_pauseWait.wakeAll();
189 if (m_tvrec)
191 }
192 m_unpauseWait.wait(&m_pauseLock, timeout.count());
193 }
194
195 if (!m_requestPause && IsPaused(true))
196 {
197 LOG(VB_RECORD, LOG_INFO, LOC +
198 QString("PauseAndWait(%1) -- unpause").arg(timeout.count()));
199 m_paused = false;
201 m_unpauseWait.wakeAll();
202 }
203
204 return IsPaused(true);
205}
206
208{
210
211 if (m_streamData->DesiredProgram() >= 0)
213}
This is a specialization of RecorderBase used to handle MPEG-2, MPEG-4, MPEG-4 AVC,...
Definition: dtvrecorder.h:35
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:161
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
bool ProcessAudioTSPacket(const TSPacket &tspacket) override
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:46
void ResetForNewFile(void) override
void BufferedWrite(const TSPacket &tspacket, bool insert=false)
bool ProcessVideoTSPacket(const TSPacket &tspacket) override
MPEGStreamData * GetStreamData(void) const
Definition: dtvrecorder.h:58
MPEGStreamData * m_streamData
Definition: dtvrecorder.h:163
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
virtual FirewireDevice * GetFirewireDevice(void)
virtual void AddListener(TSDataListener *listener)
virtual void RemoveListener(TSDataListener *listener)
virtual bool OpenPort(void)=0
virtual bool ClosePort(void)=0
bool ProcessTSPacket(const TSPacket &tspacket) override
bool PauseAndWait(std::chrono::milliseconds timeout=100ms) override
If m_requestPause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
void StartStreaming(void)
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
void AddData(const unsigned char *data, uint len) override
Callback function to add MPEG2 TS data.
void InitStreamData(void) override
FirewireRecorder(TVRec *rec, FirewireChannel *chan)
FirewireChannel * m_channel
~FirewireRecorder() override
void StopStreaming(void)
std::vector< unsigned char > m_buffer
void SetDesiredProgram(int p)
virtual void HandleTSTables(const TSPacket *tspacket)
Assembles PSIP packets and processes them.
void AddMPEGSPListener(MPEGSingleProgramStreamListener *val)
int DesiredProgram(void) const
void HandleAdaptationFieldControl(const TSPacket *tspacket)
QMutex m_pauseLock
Definition: recorderbase.h:313
bool m_requestPause
Definition: recorderbase.h:314
TVRec * m_tvrec
Definition: recorderbase.h:290
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.
bool m_recording
True while recording is actually being performed.
Definition: recorderbase.h:321
QWaitCondition m_pauseWait
Definition: recorderbase.h:316
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
bool m_requestRecording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:319
QWaitCondition m_unpauseWait
Definition: recorderbase.h:317
QWaitCondition m_recordingWait
Definition: recorderbase.h:322
bool HasAdaptationField(void) const
Definition: tspacket.h:113
unsigned int PID(void) const
Definition: tspacket.h:93
bool HasPayload(void) const
Definition: tspacket.h:116
bool TransportError(void) const
Definition: tspacket.h:86
bool Scrambled(void) const
Definition: tspacket.h:112
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:208
static constexpr unsigned int kSize
Definition: tspacket.h:261
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:143
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
Definition: tv_rec.cpp:2996
#define LOC
FirewireRecorder Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV u...
unsigned int uint
Definition: freesurround.h:24
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static constexpr uint8_t SYNC_BYTE
Definition: tspacket.h:21