00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <QString>
00023
00024
00025 #include "asistreamhandler.h"
00026 #include "asirecorder.h"
00027 #include "asichannel.h"
00028 #include "ringbuffer.h"
00029 #include "tv_rec.h"
00030
00031 #define LOC QString("ASIRec(%1): ").arg(tvrec->GetCaptureCardNum())
00032
00033 ASIRecorder::ASIRecorder(TVRec *rec, ASIChannel *channel) :
00034 DTVRecorder(rec), m_channel(channel), m_stream_handler(NULL),
00035 m_record_mpts(false)
00036 {
00037 SetStreamData(new MPEGStreamData(-1,false));
00038 if (channel->GetProgramNumber() < 0 || !channel->GetMinorChannel())
00039 _stream_data->SetListeningDisabled(true);
00040 }
00041
00042 void ASIRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00043 const QString &videodev,
00044 const QString &audiodev,
00045 const QString &vbidev)
00046 {
00047
00048
00049 DTVRecorder::SetOption("videodevice", videodev);
00050 DTVRecorder::SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
00051 SetIntOption(profile, "recordmpts");
00052 }
00053
00057 void ASIRecorder::SetOption(const QString &name, int value)
00058 {
00059 if (name == "recordmpts")
00060 m_record_mpts = (value == 1);
00061 else
00062 DTVRecorder::SetOption(name, value);
00063 }
00064
00065 void ASIRecorder::run(void)
00066 {
00067 if (!Open())
00068 {
00069 _error = "Failed to open device";
00070 LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00071 return;
00072 }
00073
00074 if (!_stream_data)
00075 {
00076 _error = "MPEGStreamData pointer has not been set";
00077 LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00078 Close();
00079 return;
00080 }
00081
00082 {
00083 QMutexLocker locker(&pauseLock);
00084 request_recording = true;
00085 recording = true;
00086 recordingWait.wakeAll();
00087 }
00088
00089 if (m_channel->HasGeneratedPAT())
00090 {
00091 const ProgramAssociationTable *pat = m_channel->GetGeneratedPAT();
00092 const ProgramMapTable *pmt = m_channel->GetGeneratedPMT();
00093 _stream_data->Reset(pat->ProgramNumber(0));
00094 _stream_data->HandleTables(MPEG_PAT_PID, *pat);
00095 _stream_data->HandleTables(pat->ProgramPID(0), *pmt);
00096 }
00097
00098
00099 if (m_channel && (m_channel->GetSIStandard() == "dvb"))
00100 _stream_data->AddListeningPID(DVB_TDT_PID);
00101
00102
00103 bool tmp = _wait_for_keyframe_option;
00104 _wait_for_keyframe_option = false;
00105 HandleSingleProgramPAT(_stream_data->PATSingleProgram());
00106 HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
00107 _wait_for_keyframe_option = tmp;
00108
00109 _stream_data->AddAVListener(this);
00110 _stream_data->AddWritingListener(this);
00111 m_stream_handler->AddListener(
00112 _stream_data, false, true,
00113 (m_record_mpts) ? ringBuffer->GetFilename() : QString());
00114
00115 while (IsRecordingRequested() && !IsErrored())
00116 {
00117 if (PauseAndWait())
00118 continue;
00119
00120 {
00121
00122 QMutexLocker locker(&pauseLock);
00123 if (!request_recording || request_pause)
00124 continue;
00125 unpauseWait.wait(&pauseLock, 100);
00126 }
00127
00128 if (!_input_pmt)
00129 {
00130 LOG(VB_GENERAL, LOG_WARNING, LOC +
00131 "Recording will not commence until a PMT is set.");
00132 usleep(5000);
00133 continue;
00134 }
00135
00136 if (!m_stream_handler->IsRunning())
00137 {
00138 _error = "Stream handler died unexpectedly.";
00139 LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00140 }
00141 }
00142
00143 m_stream_handler->RemoveListener(_stream_data);
00144 _stream_data->RemoveWritingListener(this);
00145 _stream_data->RemoveAVListener(this);
00146
00147 Close();
00148
00149 FinishRecording();
00150
00151 QMutexLocker locker(&pauseLock);
00152 recording = false;
00153 recordingWait.wakeAll();
00154 }
00155
00156 bool ASIRecorder::Open(void)
00157 {
00158 if (IsOpen())
00159 {
00160 LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
00161 return true;
00162 }
00163
00164 ResetForNewFile();
00165
00166 m_stream_handler = ASIStreamHandler::Get(m_channel->GetDevice());
00167
00168 LOG(VB_RECORD, LOG_INFO, LOC + "Opened successfully");
00169
00170 return true;
00171 }
00172
00173 bool ASIRecorder::IsOpen(void) const
00174 {
00175 return m_stream_handler;
00176 }
00177
00178 void ASIRecorder::Close(void)
00179 {
00180 LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
00181
00182 if (IsOpen())
00183 ASIStreamHandler::Return(m_stream_handler);
00184
00185 LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
00186 }