|
MythTV
0.26-pre
|
00001 00007 // MythTV includes 00008 #include "firewirerecorder.h" 00009 #include "firewirechannel.h" 00010 #include "mythlogging.h" 00011 #include "mpegtables.h" 00012 #include "mpegstreamdata.h" 00013 #include "tv_rec.h" 00014 00015 #define LOC QString("FireRecBase(%1): ").arg(channel->GetDevice()) 00016 00017 FirewireRecorder::FirewireRecorder(TVRec *rec, FirewireChannel *chan) : 00018 DTVRecorder(rec), 00019 channel(chan), isopen(false) 00020 { 00021 } 00022 00023 FirewireRecorder::~FirewireRecorder() 00024 { 00025 Close(); 00026 } 00027 00028 bool FirewireRecorder::Open(void) 00029 { 00030 if (!isopen) 00031 { 00032 isopen = channel->GetFirewireDevice()->OpenPort(); 00033 ResetForNewFile(); 00034 } 00035 return isopen; 00036 } 00037 00038 void FirewireRecorder::Close(void) 00039 { 00040 if (isopen) 00041 { 00042 channel->GetFirewireDevice()->ClosePort(); 00043 isopen = false; 00044 } 00045 } 00046 00047 void FirewireRecorder::StartStreaming(void) 00048 { 00049 channel->GetFirewireDevice()->AddListener(this); 00050 } 00051 00052 void FirewireRecorder::StopStreaming(void) 00053 { 00054 channel->GetFirewireDevice()->RemoveListener(this); 00055 } 00056 00057 void FirewireRecorder::run(void) 00058 { 00059 LOG(VB_RECORD, LOG_INFO, LOC + "run"); 00060 00061 if (!Open()) 00062 { 00063 _error = "Failed to open firewire device"; 00064 LOG(VB_GENERAL, LOG_ERR, LOC + _error); 00065 return; 00066 } 00067 00068 { 00069 QMutexLocker locker(&pauseLock); 00070 request_recording = true; 00071 recording = true; 00072 recordingWait.wakeAll(); 00073 } 00074 00075 StartStreaming(); 00076 00077 while (IsRecordingRequested() && !IsErrored()) 00078 { 00079 if (PauseAndWait()) 00080 continue; 00081 00082 if (!IsRecordingRequested()) 00083 break; 00084 00085 { // sleep 1 seconds unless StopRecording() or Unpause() is called, 00086 // just to avoid running this too often. 00087 QMutexLocker locker(&pauseLock); 00088 if (!request_recording || request_pause) 00089 continue; 00090 unpauseWait.wait(&pauseLock, 1000); 00091 } 00092 } 00093 00094 StopStreaming(); 00095 FinishRecording(); 00096 00097 QMutexLocker locker(&pauseLock); 00098 recording = false; 00099 recordingWait.wakeAll(); 00100 } 00101 00102 void FirewireRecorder::AddData(const unsigned char *data, uint len) 00103 { 00104 uint bufsz = buffer.size(); 00105 if ((SYNC_BYTE == data[0]) && (TSPacket::kSize == len) && 00106 (TSPacket::kSize > bufsz)) 00107 { 00108 if (bufsz) 00109 buffer.clear(); 00110 00111 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data))); 00112 return; 00113 } 00114 00115 buffer.insert(buffer.end(), data, data + len); 00116 bufsz += len; 00117 00118 int sync_at = -1; 00119 for (uint i = 0; (i < bufsz) && (sync_at < 0); i++) 00120 { 00121 if (buffer[i] == SYNC_BYTE) 00122 sync_at = i; 00123 } 00124 00125 if (sync_at < 0) 00126 return; 00127 00128 if (bufsz < 30 * TSPacket::kSize) 00129 return; // build up a little buffer 00130 00131 while (sync_at + TSPacket::kSize < bufsz) 00132 { 00133 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>( 00134 &buffer[0] + sync_at))); 00135 00136 sync_at += TSPacket::kSize; 00137 } 00138 00139 buffer.erase(buffer.begin(), buffer.begin() + sync_at); 00140 00141 return; 00142 } 00143 00144 bool FirewireRecorder::ProcessTSPacket(const TSPacket &tspacket) 00145 { 00146 if (tspacket.TransportError()) 00147 return true; 00148 00149 if (tspacket.Scrambled()) 00150 return true; 00151 00152 if (tspacket.HasAdaptationField()) 00153 GetStreamData()->HandleAdaptationFieldControl(&tspacket); 00154 00155 if (tspacket.HasPayload()) 00156 { 00157 const unsigned int lpid = tspacket.PID(); 00158 00159 // Pass or reject packets based on PID, and parse info from them 00160 if (lpid == GetStreamData()->VideoPIDSingleProgram()) 00161 { 00162 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 00163 BufferedWrite(tspacket); 00164 } 00165 else if (GetStreamData()->IsAudioPID(lpid)) 00166 { 00167 _buffer_packets = !FindAudioKeyframes(&tspacket); 00168 BufferedWrite(tspacket); 00169 } 00170 else if (GetStreamData()->IsListeningPID(lpid)) 00171 GetStreamData()->HandleTSTables(&tspacket); 00172 else if (GetStreamData()->IsWritingPID(lpid)) 00173 BufferedWrite(tspacket); 00174 } 00175 00176 return true; 00177 } 00178 00179 void FirewireRecorder::SetOptionsFromProfile(RecordingProfile *profile, 00180 const QString &videodev, 00181 const QString &audiodev, 00182 const QString &vbidev) 00183 { 00184 (void)videodev; 00185 (void)audiodev; 00186 (void)vbidev; 00187 (void)profile; 00188 } 00189 00190 // documented in recorderbase.cpp 00191 bool FirewireRecorder::PauseAndWait(int timeout) 00192 { 00193 QMutexLocker locker(&pauseLock); 00194 if (request_pause) 00195 { 00196 LOG(VB_RECORD, LOG_INFO, LOC + 00197 QString("PauseAndWait(%1) -- pause").arg(timeout)); 00198 if (!IsPaused(true)) 00199 { 00200 StopStreaming(); 00201 paused = true; 00202 pauseWait.wakeAll(); 00203 if (tvrec) 00204 tvrec->RecorderPaused(); 00205 } 00206 unpauseWait.wait(&pauseLock, timeout); 00207 } 00208 00209 if (!request_pause && IsPaused(true)) 00210 { 00211 LOG(VB_RECORD, LOG_INFO, LOC + 00212 QString("PauseAndWait(%1) -- unpause").arg(timeout)); 00213 StartStreaming(); 00214 unpauseWait.wakeAll(); 00215 } 00216 00217 return IsPaused(true); 00218 } 00219 00220 void FirewireRecorder::SetStreamData(void) 00221 { 00222 _stream_data->AddMPEGSPListener(this); 00223 00224 if (_stream_data->DesiredProgram() >= 0) 00225 _stream_data->SetDesiredProgram(_stream_data->DesiredProgram()); 00226 }
1.7.6.1