00001
00007
00008 #include "firewirerecorder.h"
00009 #include "firewirechannel.h"
00010 #include "mythcontext.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 #define LOC_ERR QString("FireRecBase(%1), Error: ").arg(channel->GetDevice())
00017
00018 FirewireRecorder::FirewireRecorder(TVRec *rec, FirewireChannel *chan) :
00019 DTVRecorder(rec), _mpeg_stream_data(NULL),
00020 channel(chan), isopen(false)
00021 {
00022 }
00023
00024 FirewireRecorder::~FirewireRecorder()
00025 {
00026 SetStreamData(NULL);
00027 Close();
00028 }
00029
00030 bool FirewireRecorder::Open(void)
00031 {
00032 if (!isopen)
00033 isopen = channel->GetFirewireDevice()->OpenPort();
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::StartRecording(void)
00058 {
00059 VERBOSE(VB_RECORD, LOC + "StartRecording");
00060
00061 if (!Open())
00062 {
00063 _error = true;
00064 return;
00065 }
00066
00067 _request_recording = true;
00068 _recording = true;
00069
00070 StartStreaming();
00071
00072 while (_request_recording)
00073 {
00074 if (!PauseAndWait())
00075 usleep(50 * 1000);
00076 }
00077
00078 StopStreaming();
00079 FinishRecording();
00080
00081 _recording = false;
00082 }
00083
00084 void FirewireRecorder::AddData(const unsigned char *data, uint len)
00085 {
00086 uint bufsz = buffer.size();
00087 if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) &&
00088 (TSPacket::SIZE > bufsz))
00089 {
00090 if (bufsz)
00091 buffer.clear();
00092
00093 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
00094 return;
00095 }
00096
00097 buffer.insert(buffer.end(), data, data + len);
00098 bufsz += len;
00099
00100 int sync_at = -1;
00101 for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
00102 {
00103 if (buffer[i] == SYNC_BYTE)
00104 sync_at = i;
00105 }
00106
00107 if (sync_at < 0)
00108 return;
00109
00110 if (bufsz < 30 * TSPacket::SIZE)
00111 return;
00112
00113 while (sync_at + TSPacket::SIZE < bufsz)
00114 {
00115 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
00116 &buffer[0] + sync_at)));
00117
00118 sync_at += TSPacket::SIZE;
00119 }
00120
00121 buffer.erase(buffer.begin(), buffer.begin() + sync_at);
00122
00123 return;
00124 }
00125
00126 void FirewireRecorder::ProcessTSPacket(const TSPacket &tspacket)
00127 {
00128 if (tspacket.TransportError())
00129 return;
00130
00131 if (tspacket.ScramplingControl())
00132 return;
00133
00134 if (tspacket.HasAdaptationField())
00135 GetStreamData()->HandleAdaptationFieldControl(&tspacket);
00136
00137 if (tspacket.HasPayload())
00138 {
00139 const unsigned int lpid = tspacket.PID();
00140
00141
00142 if (lpid == GetStreamData()->VideoPIDSingleProgram())
00143 {
00144 _buffer_packets = !FindMPEG2Keyframes(&tspacket);
00145 BufferedWrite(tspacket);
00146 }
00147 else if (GetStreamData()->IsAudioPID(lpid))
00148 {
00149 _buffer_packets = !FindAudioKeyframes(&tspacket);
00150 BufferedWrite(tspacket);
00151 }
00152 else if (GetStreamData()->IsListeningPID(lpid))
00153 GetStreamData()->HandleTSTables(&tspacket);
00154 else if (GetStreamData()->IsWritingPID(lpid))
00155 BufferedWrite(tspacket);
00156 }
00157 }
00158
00159 void FirewireRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00160 const QString &videodev,
00161 const QString &audiodev,
00162 const QString &vbidev)
00163 {
00164 (void)videodev;
00165 (void)audiodev;
00166 (void)vbidev;
00167 (void)profile;
00168 }
00169
00170
00171 bool FirewireRecorder::PauseAndWait(int timeout)
00172 {
00173 if (request_pause)
00174 {
00175 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause");
00176 if (!paused)
00177 {
00178 StopStreaming();
00179 paused = true;
00180 pauseWait.wakeAll();
00181 if (tvrec)
00182 tvrec->RecorderPaused();
00183 }
00184 unpauseWait.wait(timeout);
00185 }
00186 if (!request_pause && paused)
00187 {
00188 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause");
00189 StartStreaming();
00190 paused = false;
00191 }
00192 return paused;
00193 }
00194
00195 void FirewireRecorder::SetStreamData(MPEGStreamData *data)
00196 {
00197 if (data == _mpeg_stream_data)
00198 return;
00199
00200 MPEGStreamData *old_data = _mpeg_stream_data;
00201 _mpeg_stream_data = data;
00202 if (old_data)
00203 delete old_data;
00204
00205 if (data)
00206 {
00207 data->AddMPEGSPListener(this);
00208
00209 if (data->DesiredProgram() >= 0)
00210 data->SetDesiredProgram(data->DesiredProgram());
00211 }
00212 }
00213
00214 void FirewireRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
00215 {
00216 if (!pat)
00217 return;
00218
00219 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
00220 pat->tsheader()->SetContinuityCounter(next);
00221 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
00222 }
00223
00224 void FirewireRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
00225 {
00226 if (!pmt)
00227 return;
00228
00229 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
00230 pmt->tsheader()->SetContinuityCounter(next);
00231 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
00232 }