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 Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "io/mythmediabuffer.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_streamData)
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_requestRecording = true;
63  m_recording = true;
64  m_recordingWait.wakeAll();
65  }
66 
68  {
73  m_streamData->HandleTables(pat->ProgramPID(0), *pmt);
74  LOG(VB_GENERAL, LOG_INFO, LOC + "PMT set");
75  }
76 
77  StartNewFile();
78 
80  m_seenSps = false;
81 
85 
87 
88  while (IsRecordingRequested() && !IsErrored())
89  {
90  if (PauseAndWait())
91  continue;
92 
93  if (!m_inputPmt)
94  {
95  LOG(VB_GENERAL, LOG_WARNING, LOC +
96  "Recording will not commence until a PMT is set.");
97  usleep(5000);
98  continue;
99  }
100 
101  if (!m_streamHandler->IsRunning())
102  {
103  m_error = "Stream handler died unexpectedly.";
104  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
105  }
106 
107  if (m_streamHandler->IsDamaged())
108  {
109  LOG(VB_GENERAL, LOG_INFO, LOC +
110  QString("Recording is damaged. Setting status to %1")
112  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
114  }
115  }
116 
117  StopStreaming();
118 
122 
123  Close();
124 
125  FinishRecording();
126 
127  QMutexLocker locker(&m_pauseLock);
128  m_recording = false;
129  m_recordingWait.wakeAll();
130 }
131 
133 {
134  if (IsOpen())
135  {
136  LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
137  return true;
138  }
139 
140  ResetForNewFile();
141 
144  m_channel->GetMajorID());
145 
146  if (m_streamHandler)
147  {
148  if (m_streamHandler->IsAppOpen())
149  LOG(VB_RECORD, LOG_INFO, LOC + "Opened successfully");
150  else
151  {
153  (m_tvrec ? m_tvrec->GetInputId() : -1));
154 
155  return false;
156  }
157  return true;
158  }
159 
160  Close();
161  LOG(VB_GENERAL, LOG_ERR, LOC + "Open failed");
162  return false;
163 }
164 
166 {
167  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
168 
169  if (IsOpen())
171  (m_tvrec ? m_tvrec->GetInputId() : -1));
172 
173  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
174 }
175 
176 bool ExternalRecorder::PauseAndWait(std::chrono::milliseconds timeout)
177 {
178  QMutexLocker locker(&m_pauseLock);
179  if (m_requestPause)
180  {
181  if (!IsPaused(true))
182  {
183  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
184 
186  StopStreaming();
187 
188  m_paused = true;
189  m_pauseWait.wakeAll();
190 
191  if (m_tvrec)
193  }
194  }
195  else if (IsPaused(true))
196  {
197  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
198 
199  // The SignalMonitor will StartStreaming
200 
201  if (m_h2645Parser != nullptr)
202  m_h2645Parser->Reset();
203 
204  if (m_streamData)
206 
207  m_paused = false;
209  StartStreaming();
210  }
211 
212  // Always wait a little bit, unless woken up
213  m_unpauseWait.wait(&m_pauseLock, timeout.count());
214 
215  return IsPaused(true);
216 }
217 
219 {
220  LOG(VB_RECORD, LOG_INFO, LOC + "StartStreaming");
222 }
223 
225 {
227 }
DTVRecorder::HandleSingleProgramPMT
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
Definition: dtvrecorder.cpp:1409
ProgramAssociationTable::ProgramPID
uint ProgramPID(uint i) const
Definition: mpegtables.h:648
PID::MPEG_PAT_PID
@ MPEG_PAT_PID
Definition: mpegtables.h:211
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
ExternalRecorder.h
ExternalStreamHandler::ClearDamaged
void ClearDamaged(void)
Definition: ExternalStreamHandler.h:92
DTVRecorder::m_inputPmt
ProgramMapTable * m_inputPmt
PMT on input side.
Definition: dtvrecorder.h:174
DTVRecorder::ResetForNewFile
void ResetForNewFile(void) override
Definition: dtvrecorder.cpp:140
ExternalRecorder::StopStreaming
bool StopStreaming(void)
Definition: ExternalRecorder.cpp:224
ProgramMapTable
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:694
ExternalRecorder::run
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
Definition: ExternalRecorder.cpp:43
H2645Parser::Reset
virtual void Reset(void)
Definition: H2645Parser.cpp:92
ExternalStreamHandler::IsDamaged
bool IsDamaged(void) const
Definition: ExternalStreamHandler.h:91
ExternalRecorder::Close
void Close(void)
Definition: ExternalRecorder.cpp:165
ExternalStreamHandler::StopStreaming
bool StopStreaming(void)
Definition: ExternalStreamHandler.cpp:1183
RecorderBase::m_tvrec
TVRec * m_tvrec
Definition: recorderbase.h:292
DTVRecorder::IsErrored
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:46
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
kSingleRecord
@ kSingleRecord
Definition: recordingtypes.h:22
DTVRecorder::FinishRecording
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
Definition: dtvrecorder.cpp:126
ExternalRecorder::m_channel
ExternalChannel * m_channel
Definition: ExternalRecorder.h:50
ExternalStreamHandler.h
DTVChannel::GetGeneratedPMT
const ProgramMapTable * GetGeneratedPMT(void) const
Definition: dtvchannel.h:138
MPEGStreamData::PMTSingleProgram
const ProgramMapTable * PMTSingleProgram(void) const
Definition: mpegstreamdata.h:266
ExternalRecorder::IsOpen
bool IsOpen(void) const
Definition: ExternalRecorder.h:39
StreamHandler::RemoveListener
virtual void RemoveListener(MPEGStreamData *data)
Definition: streamhandler.cpp:80
RecorderBase::m_pauseLock
QMutex m_pauseLock
Definition: recorderbase.h:315
RecStatus::toString
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
Definition: recordingstatus.cpp:40
RecorderBase::m_requestPause
bool m_requestPause
Definition: recorderbase.h:316
ExternalRecorder::StartNewFile
void StartNewFile(void) override
Definition: ExternalRecorder.cpp:35
RecorderBase::m_recordingWait
QWaitCondition m_recordingWait
Definition: recorderbase.h:324
TVRec::RecorderPaused
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
Definition: tv_rec.cpp:3000
ExternalChannel::GetDevice
QString GetDevice(void) const override
Returns String representing device, useful for debugging.
Definition: ExternalChannel.h:44
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:234
RecorderBase::m_paused
bool m_paused
Definition: recorderbase.h:317
MPEGStreamData::PATSingleProgram
const ProgramAssociationTable * PATSingleProgram(void) const
Definition: mpegstreamdata.h:264
DTVRecorder::HandleSingleProgramPAT
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
Definition: dtvrecorder.cpp:1389
ProgramAssociationTable::ProgramNumber
uint ProgramNumber(uint i) const
Definition: mpegtables.h:645
MPEGStreamData::HandleTables
virtual bool HandleTables(uint pid, const PSIPTable &psip)
Process PSIP packets.
Definition: mpegstreamdata.cpp:668
RecStatus::Failing
@ Failing
Definition: recordingstatus.h:18
DTVChannel::GetGeneratedPAT
const ProgramAssociationTable * GetGeneratedPAT(void) const
Definition: dtvchannel.h:137
ExternalRecorder::PauseAndWait
bool PauseAndWait(std::chrono::milliseconds timeout=100ms) override
If m_requestPause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
Definition: ExternalRecorder.cpp:176
ExternalRecorder::StartStreaming
bool StartStreaming(void)
Definition: ExternalRecorder.cpp:218
MPEGStreamData::RemoveWritingListener
void RemoveWritingListener(TSPacketListener *val)
Definition: mpegstreamdata.cpp:1665
RecorderBase::IsRecordingRequested
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.
Definition: recorderbase.cpp:256
DTVRecorder::m_h2645Parser
H2645Parser * m_h2645Parser
Definition: dtvrecorder.h:152
DTVRecorder::m_seenSps
bool m_seenSps
Definition: dtvrecorder.h:151
ExternalStreamHandler::Get
static ExternalStreamHandler * Get(const QString &devname, int inputid, int majorid)
Definition: ExternalStreamHandler.cpp:464
ExternalRecorder::Open
bool Open(void)
Definition: ExternalRecorder.cpp:132
ProgramAssociationTable
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
Definition: mpegtables.h:617
ExternalStreamHandler::StartStreaming
bool StartStreaming(void)
Definition: ExternalStreamHandler.cpp:1133
mythmediabuffer.h
ExternalStreamHandler::IsAppOpen
bool IsAppOpen(void)
Definition: ExternalStreamHandler.cpp:1007
RecorderBase::m_pauseWait
QWaitCondition m_pauseWait
Definition: recorderbase.h:318
MPEGStreamData::AddAVListener
void AddAVListener(TSPacketListenerAV *val)
Definition: mpegstreamdata.cpp:1679
DTVRecorder::m_waitForKeyframeOption
bool m_waitForKeyframeOption
Wait for the a GOP/SEQ-start before sending data.
Definition: dtvrecorder.h:155
RecorderBase::SetRecordingStatus
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
Definition: recorderbase.cpp:401
DTVRecorder::m_streamData
MPEGStreamData * m_streamData
Definition: dtvrecorder.h:163
MPEGStreamData::AddWritingListener
void AddWritingListener(TSPacketListener *val)
Definition: mpegstreamdata.cpp:1654
MPEGStreamData::DesiredProgram
int DesiredProgram(void) const
Definition: mpegstreamdata.h:260
DTVRecorder::m_error
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:161
ExternalChannel.h
RecorderBase::m_recording
bool m_recording
True while recording is actually being performed.
Definition: recorderbase.h:323
MPEGStreamData::Reset
virtual void Reset(void)
Definition: mpegstreamdata.h:94
tv_rec.h
ChannelBase::GetInputID
virtual int GetInputID(void) const
Definition: channelbase.h:67
LOC
#define LOC
Definition: ExternalRecorder.cpp:31
StreamHandler::AddListener
virtual void AddListener(MPEGStreamData *data, bool allow_section_reader=false, bool needs_buffering=false, const QString &output_file=QString())
Definition: streamhandler.cpp:35
DTVChannel::HasGeneratedPAT
bool HasGeneratedPAT(void) const
Definition: dtvchannel.h:135
StreamHandler::IsRunning
bool IsRunning(void) const
Definition: streamhandler.cpp:163
RecorderBase::m_unpauseWait
QWaitCondition m_unpauseWait
Definition: recorderbase.h:319
ChannelBase::GetMajorID
int GetMajorID(void)
Definition: channelbase.cpp:860
MPEGStreamData::RemoveAVListener
void RemoveAVListener(TSPacketListenerAV *val)
Definition: mpegstreamdata.cpp:1700
ExternalStreamHandler::Return
static void Return(ExternalStreamHandler *&ref, int inputid)
Definition: ExternalStreamHandler.cpp:495
RecorderBase::IsPaused
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
Definition: recorderbase.cpp:287
RecorderBase::m_requestRecording
bool m_requestRecording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:321
ExternalRecorder::m_streamHandler
ExternalStreamHandler * m_streamHandler
Definition: ExternalRecorder.h:51