MythTV  0.26-pre
firewirerecorder.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends