MythTV  master
ExternalRecorder.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  * Class ExternalRecorder
3  *
4  * Copyright (C) John Poet 2013
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 // Qt includes
22 #include <QString>
23 
24 // MythTV includes
25 #include "ExternalStreamHandler.h"
26 #include "ExternalRecorder.h"
27 #include "ExternalChannel.h"
28 #include "ringbuffer.h"
29 #include "tv_rec.h"
30 
31 #define LOC QString("ExternalRec[%1](%2): ") \
32  .arg(m_channel->GetInputID()) \
33  .arg(m_channel->GetDescription())
34 
36 {
37  // Make sure the first things in the file are a PAT & PMT
40 }
41 
42 
44 {
45  if (!Open())
46  {
47  m_error = "Failed to open device";
48  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
49  return;
50  }
51 
52  if (!m_stream_data)
53  {
54  m_error = "MPEGStreamData pointer has not been set";
55  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
56  Close();
57  return;
58  }
59 
60  {
61  QMutexLocker locker(&m_pauseLock);
62  m_request_recording = true;
63  m_recording = true;
64  m_recordingWait.wakeAll();
65  }
66 
68  {
73  m_stream_data->HandleTables(pat->ProgramPID(0), *pmt);
74  LOG(VB_GENERAL, LOG_INFO, LOC + "PMT set");
75  }
76 
77  StartNewFile();
78 
81  m_seen_sps = false;
82 
86 
88 
89  while (IsRecordingRequested() && !IsErrored())
90  {
91  if (PauseAndWait())
92  continue;
93 
94  if (!m_input_pmt)
95  {
96  LOG(VB_GENERAL, LOG_WARNING, LOC +
97  "Recording will not commence until a PMT is set.");
98  usleep(5000);
99  continue;
100  }
101 
102  if (!m_stream_handler->IsRunning())
103  {
104  m_error = "Stream handler died unexpectedly.";
105  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
106  }
107  }
108 
109  StopStreaming();
110 
114 
115  Close();
116 
117  FinishRecording();
118 
119  QMutexLocker locker(&m_pauseLock);
120  m_recording = false;
121  m_recordingWait.wakeAll();
122 }
123 
125 {
126  QString result;
127 
128  if (IsOpen())
129  {
130  LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
131  return true;
132  }
133 
134  ResetForNewFile();
135 
138  m_channel->GetMajorID());
139 
140  if (m_stream_handler)
141  {
143  LOG(VB_RECORD, LOG_INFO, LOC + "Opened successfully");
144  else
145  {
147  (m_tvrec ? m_tvrec->GetInputId() : -1));
148 
149  return false;
150  }
151  return true;
152  }
153 
154  LOG(VB_GENERAL, LOG_ERR, LOC + "Open failed");
155  return false;
156 }
157 
159 {
160  QString result;
161 
162  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
163 
164  if (IsOpen())
166  (m_tvrec ? m_tvrec->GetInputId() : -1));
167 
168  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
169 }
170 
172 {
173  QMutexLocker locker(&m_pauseLock);
174  if (m_request_pause)
175  {
176  if (!IsPaused(true))
177  {
178  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
179 
180  StopStreaming();
181 
182  m_paused = true;
183  m_pauseWait.wakeAll();
184 
185  if (m_tvrec)
187  }
188  }
189  else if (IsPaused(true))
190  {
191  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
192 
193  // The SignalMonitor will StartStreaming
194 
195  if (m_stream_data)
197 
198  m_paused = false;
199  }
200 
201  // Always wait a little bit, unless woken up
203 
204  return IsPaused(true);
205 }
206 
208 {
209  LOG(VB_RECORD, LOG_INFO, LOC + "StartStreaming");
211 }
212 
214 {
216 }
H264Parser m_h264_parser
Definition: dtvrecorder.h:153
const ProgramAssociationTable * PATSingleProgram(void) const
virtual void Reset(void)
uint GetInputId(void)
Returns the inputid.
Definition: tv_rec.h:241
bool m_wait_for_keyframe_option
Wait for the a GOP/SEQ-start before sending data.
Definition: dtvrecorder.h:156
QString GetDevice(void) const override
Returns String representing device, useful for debugging.
bool HasGeneratedPAT(void) const
Definition: dtvchannel.h:137
QMutex m_pauseLock
Definition: recorderbase.h:326
void ResetForNewFile(void) override
uint ProgramNumber(uint i) const
Definition: mpegtables.h:607
virtual void RemoveListener(MPEGStreamData *data)
const ProgramAssociationTable * GetGeneratedPAT(void) const
Definition: dtvchannel.h:139
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
ExternalChannel * m_channel
virtual bool HandleTables(uint pid, const PSIPTable &psip)
Assembles PSIP packets and processes them.
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:48
int DesiredProgram(void) const
ExternalStreamHandler * m_stream_handler
void StartNewFile(void) override
bool m_request_recording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:332
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
void Reset(void)
Definition: H264Parser.cpp:105
QWaitCondition m_unpauseWait
Definition: recorderbase.h:330
ProgramMapTable * m_input_pmt
PMT on input side.
Definition: dtvrecorder.h:175
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
virtual void AddListener(MPEGStreamData *data, bool allow_section_reader=false, bool needs_buffering=false, QString output_file=QString())
MPEGStreamData * m_stream_data
Definition: dtvrecorder.h:164
void RemoveWritingListener(TSPacketListener *)
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
Definition: tv_rec.cpp:2929
bool PauseAndWait(int timeout=100) override
If m_request_pause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
bool m_seen_sps
Definition: dtvrecorder.h:152
void AddAVListener(TSPacketListenerAV *)
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
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
Definition: mpegtables.h:579
static ExternalStreamHandler * Get(const QString &devname, int inputid, int majorid)
#define LOC
bool m_request_pause
Definition: recorderbase.h:327
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
TVRec * m_tvrec
Definition: recorderbase.h:303
const ProgramMapTable * PMTSingleProgram(void) const
void AddWritingListener(TSPacketListener *)
virtual int GetInputID(void) const
Definition: channelbase.h:67
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:162
void RemoveAVListener(TSPacketListenerAV *)
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:656
const ProgramMapTable * GetGeneratedPMT(void) const
Definition: dtvchannel.h:140
bool IsRunning(void) const
static void Return(ExternalStreamHandler *&ref, int inputid)
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
int GetMajorID(void)
bool IsOpen(void) const
uint ProgramPID(uint i) const
Definition: mpegtables.h:610
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.