MythTV  master
asirecorder.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  * Class ASIRecorder
3  *
4  * Copyright (C) Daniel Kristjansson 2010
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 // Qt includes
22 #include <QString>
23 
24 // MythTV includes
25 #include "tsstreamdata.h"
26 #include "asistreamhandler.h"
27 #include "asirecorder.h"
28 #include "asichannel.h"
29 #include "ringbuffer.h"
30 #include "tv_rec.h"
31 
32 #define LOC QString("ASIRec[%1](%2): ") \
33  .arg(m_tvrec ? m_tvrec->GetInputId() : -1) \
34  .arg(m_channel->GetDevice())
35 
37  DTVRecorder(rec), m_channel(channel)
38 {
39  if (channel->GetFormat().compare("MPTS") == 0)
40  {
41  // MPTS only. Use TSStreamData to write out unfiltered data
42  LOG(VB_RECORD, LOG_INFO, LOC + "Using TSStreamData");
44  m_record_mpts_only = true;
45  m_record_mpts = false;
46  }
47  else
48  {
49  LOG(VB_RECORD, LOG_INFO, LOC + "Using MPEGStreamData");
50  SetStreamData(new MPEGStreamData(-1, rec ? rec->GetInputId() : -1,
51  false));
52  if (channel->GetProgramNumber() < 0 || !channel->GetMinorChannel())
54  }
55 }
56 
58  const QString &videodev,
59  const QString &/*audiodev*/,
60  const QString &/*vbidev*/)
61 {
62  // We don't want to call DTVRecorder::SetOptionsFromProfile() since
63  // we do not have a "recordingtype" in our profile.
64  DTVRecorder::SetOption("videodevice", videodev);
65  DTVRecorder::SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
66  SetIntOption(profile, "recordmpts");
67 }
68 
70 {
71  if (!m_record_mpts_only)
72  {
73  if (m_record_mpts)
75 
76  // Make sure the first things in the file are a PAT & PMT
79  }
80 }
81 
82 
83 void ASIRecorder::run(void)
84 {
85  if (!Open())
86  {
87  m_error = "Failed to open device";
88  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
89  return;
90  }
91 
92  if (!m_stream_data)
93  {
94  m_error = "MPEGStreamData pointer has not been set";
95  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
96  Close();
97  return;
98  }
99 
100  {
101  QMutexLocker locker(&m_pauseLock);
102  m_request_recording = true;
103  m_recording = true;
104  m_recordingWait.wakeAll();
105  }
106 
107  if (m_channel->HasGeneratedPAT())
108  {
110  const ProgramMapTable *pmt = m_channel->GetGeneratedPMT();
113  m_stream_data->HandleTables(pat->ProgramPID(0), *pmt);
114  }
115 
116  // Listen for time table on DVB standard streams
117  if (m_channel && (m_channel->GetSIStandard() == "dvb"))
119 
120  StartNewFile();
121 
125  m_stream_data, false, true,
126  (m_record_mpts) ? m_ringBuffer->GetFilename() : QString());
127 
128  while (IsRecordingRequested() && !IsErrored())
129  {
130  if (PauseAndWait())
131  continue;
132 
133  { // sleep 100 milliseconds unless StopRecording() or Unpause()
134  // is called, just to avoid running this too often.
135  QMutexLocker locker(&m_pauseLock);
137  continue;
138  m_unpauseWait.wait(&m_pauseLock, 100);
139  }
140 
142  {
143  LOG(VB_GENERAL, LOG_WARNING, LOC +
144  "Recording will not commence until a PMT is set.");
145  usleep(5000);
146  continue;
147  }
148 
149  if (!m_stream_handler->IsRunning())
150  {
151  m_error = "Stream handler died unexpectedly.";
152  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
153  }
154  }
155 
159 
160  Close();
161 
162  FinishRecording();
163 
164  QMutexLocker locker(&m_pauseLock);
165  m_recording = false;
166  m_recordingWait.wakeAll();
167 }
168 
170 {
171  if (IsOpen())
172  {
173  LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
174  return true;
175  }
176 
177  ResetForNewFile();
178 
180  m_tvrec ? m_tvrec->GetInputId() : -1);
181 
182 
183  LOG(VB_RECORD, LOG_INFO, LOC + "Opened successfully");
184 
185  return true;
186 }
187 
188 bool ASIRecorder::IsOpen(void) const
189 {
190  return m_stream_handler;
191 }
192 
194 {
195  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
196 
197  if (IsOpen())
199  m_tvrec ? m_tvrec->GetInputId() : -1);
200 
201  LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
202 }
const ProgramAssociationTable * PATSingleProgram(void) const
virtual void Reset(void)
This is a specialization of RecorderBase used to handle MPEG-2, MPEG-4, MPEG-4 AVC,...
Definition: dtvrecorder.h:28
uint GetInputId(void)
Returns the inputid.
Definition: tv_rec.h:241
bool HasGeneratedPAT(void) const
Definition: dtvchannel.h:137
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
Definition: asirecorder.cpp:57
int GetProgramNumber(void) const
Returns program number in PAT, -1 if unknown.
Definition: dtvchannel.h:91
static ASIStreamHandler * Get(const QString &devname, int inputid)
QMutex m_pauseLock
Definition: recorderbase.h:326
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
Definition: asirecorder.cpp:83
void ResetForNewFile(void) override
void AddListener(MPEGStreamData *data, bool=false, bool=false, QString output_file=QString()) override
bool m_record_mpts
Definition: dtvrecorder.h:179
uint ProgramNumber(uint i) const
Definition: mpegtables.h:607
bool Open(void)
virtual void RemoveListener(MPEGStreamData *data)
QString GetFilename(void) const
Returns name of file used by this RingBuffer.
const ProgramAssociationTable * GetGeneratedPAT(void) const
Definition: dtvchannel.h:139
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
virtual bool HandleTables(uint pid, const PSIPTable &psip)
Assembles PSIP packets and processes them.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString GetDevice(void) const override
Returns String representing device, useful for debugging.
Definition: asichannel.h:35
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:48
virtual bool PauseAndWait(int timeout=100)
If m_request_pause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
ASIRecorder(TVRec *rec, ASIChannel *channel)
Definition: asirecorder.cpp:36
bool m_request_recording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:332
virtual void SetStreamData(MPEGStreamData *data)
QWaitCondition m_unpauseWait
Definition: recorderbase.h:330
ProgramMapTable * m_input_pmt
PMT on input side.
Definition: dtvrecorder.h:175
RingBuffer * m_ringBuffer
Definition: recorderbase.h:304
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:150
uint GetMinorChannel(void) const
Returns minor channel, 0 if unknown.
Definition: dtvchannel.h:99
QString GetSetting(const QString &key, const QString &defaultval="")
MPEGStreamData * m_stream_data
Definition: dtvrecorder.h:164
QString GetFormat(void)
Definition: dtvchannel.h:47
ASIChannel * m_channel
Definition: asirecorder.h:73
void RemoveWritingListener(TSPacketListener *)
bool IsOpen(void) const
void AddAVListener(TSPacketListenerAV *)
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
void SetOption(const QString &name, const QString &value) override
Set an specific option.
Definition: dtvrecorder.cpp:83
#define LOC
Definition: asirecorder.cpp:32
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
void Close(void)
ASIStreamHandler * m_stream_handler
Definition: asirecorder.h:74
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 *)
void SetIntOption(RecordingProfile *profile, const QString &name)
Convenience function used to set integer options from a profile.
bool m_record_mpts_only
Definition: dtvrecorder.h:180
void SetListeningDisabled(bool lt)
Specialized version of MPEGStreamData which is used to 'blindly' record the entire MPTS transport fro...
Definition: tsstreamdata.h:11
static void Return(ASIStreamHandler *&ref, int inputid)
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:162
QString GetSIStandard(void) const
Returns PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:44
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
virtual bool AddNamedOutputFile(const QString &filename)
Called with _listener_lock locked just after adding new output file.
Encapsulates data about MPEG stream and emits events for each table.
bool IsRunning(void) const
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
void StartNewFile(void) override
Definition: asirecorder.cpp:69
uint ProgramPID(uint i) const
Definition: mpegtables.h:610
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.