|
MythTV
0.26-pre
|
00001 /* -*- Mode: c++ -*- 00002 * Class ASIRecorder 00003 * 00004 * Copyright (C) Daniel Kristjansson 2010 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 */ 00020 00021 // Qt includes 00022 #include <QString> 00023 00024 // MythTV includes 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 // We don't want to call DTVRecorder::SetOptionsFromProfile() since 00048 // we do not have a "recordingtype" in our profile. 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 // Listen for time table on DVB standard streams 00099 if (m_channel && (m_channel->GetSIStandard() == "dvb")) 00100 _stream_data->AddListeningPID(DVB_TDT_PID); 00101 00102 // Make sure the first things in the file are a PAT & PMT 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 { // sleep 100 milliseconds unless StopRecording() or Unpause() 00121 // is called, just to avoid running this too often. 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 }
1.7.6.1