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