Permalink
Browse files

Fixes #9830. Refs #10519. Fixes channel change on PVR350.

The drivers for some V4L devices require you to explicitly stop and restart streaming when sending certain ioctl's to the device. We already pause and unpause the recorder when issuing these commands so this adds a close(readfd) to the code that is run on pause and reopens readfd on the unpause code. This also means the DeviceReadBuffer needs to be reset with the new readfd, so we do that as well.
  • Loading branch information...
1 parent 79d7af9 commit f81f712537b63502814d1f274c7da14196cedd8c @daniel-kristjansson daniel-kristjansson committed Apr 2, 2012
Showing with 46 additions and 76 deletions.
  1. +44 −74 mythtv/libs/libmythtv/mpegrecorder.cpp
  2. +2 −2 mythtv/libs/libmythtv/mpegrecorder.h
@@ -968,14 +968,7 @@ void MpegRecorder::run(void)
else if (_device_read_buffer)
{
LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
-
- if (!StartEncoding(readfd))
- {
- LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start recording");
- _error = "Failed to start recording";
- }
- else
- _device_read_buffer->Start();
+ StartEncoding();
}
QByteArray vdevice = videodevice.toAscii();
@@ -1005,25 +998,6 @@ void MpegRecorder::run(void)
}
}
}
- else
- {
- if (readfd < 0)
- {
- if (!Open())
- {
- _error = "Failed to open device";
- break;
- }
-
- if (readfd < 0)
- {
- LOG(VB_GENERAL, LOG_ERR, LOC +
- QString("Failed to open device '%1'")
- .arg(videodevice));
- continue;
- }
- }
- }
if (_device_read_buffer)
{
@@ -1138,18 +1112,7 @@ void MpegRecorder::run(void)
LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
- pauseLock.lock();
- if (_device_read_buffer)
- {
- if (_device_read_buffer->IsRunning())
- _device_read_buffer->Stop();
-
- delete _device_read_buffer;
- _device_read_buffer = NULL;
- }
- pauseLock.unlock();
-
- StopEncoding(readfd);
+ StopEncoding();
{
QMutexLocker locker(&pauseLock);
@@ -1183,10 +1146,7 @@ void MpegRecorder::run(void)
void MpegRecorder::StopRecording(void)
{
- pauseLock.lock();
- if (_device_read_buffer && _device_read_buffer->IsRunning())
- _device_read_buffer->Stop();
- pauseLock.unlock();
+ MpegRecorder::StopEncoding();
V4LRecorder::StopRecording();
}
@@ -1246,13 +1206,7 @@ bool MpegRecorder::PauseAndWait(int timeout)
{
LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
- if (_device_read_buffer)
- {
- _device_read_buffer->SetRequestPause(true);
- _device_read_buffer->WaitForPaused(4000);
- }
-
- StopEncoding(readfd);
+ StopEncoding();
paused = true;
pauseWait.wakeAll();
@@ -1277,10 +1231,7 @@ bool MpegRecorder::PauseAndWait(int timeout)
SetV4L2DeviceOptions(chanfd);
}
- StartEncoding(readfd);
-
- if (_device_read_buffer)
- _device_read_buffer->SetRequestPause(false);
+ StartEncoding();
if (_stream_data)
_stream_data->Reset(_stream_data->DesiredProgram());
@@ -1295,11 +1246,9 @@ void MpegRecorder::RestartEncoding(void)
{
LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
- _device_read_buffer->Stop();
-
QMutexLocker locker(&start_stop_encoding_lock);
- StopEncoding(readfd);
+ StopEncoding();
// Make sure the next things in the file are a PAT & PMT
if (_stream_data &&
@@ -1313,19 +1262,11 @@ void MpegRecorder::RestartEncoding(void)
if (driver == "hdpvr") // HD-PVR will sometimes reset to defaults
SetV4L2DeviceOptions(chanfd);
- if (!StartEncoding(readfd))
- {
- if (0 != close(readfd))
- LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
-
- readfd = -1;
- return;
- }
- _device_read_buffer->Start();
+ StartEncoding();
}
-bool MpegRecorder::StartEncoding(int fd)
+bool MpegRecorder::StartEncoding(void)
{
QMutexLocker locker(&start_stop_encoding_lock);
@@ -1338,7 +1279,19 @@ bool MpegRecorder::StartEncoding(int fd)
LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
- bool started = 0 == ioctl(fd, VIDIOC_ENCODER_CMD, &command);
+ if (readfd < 0)
+ {
+ readfd = open(videodevice.toAscii().constData(), O_RDWR | O_NONBLOCK);
+ if (readfd < 0)
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC +
+ "StartEncoding: Can't open video device." + ENO);
+ _error = "Failed to start recording";
+ return false;
+ }
+ }
+
+ bool started = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
if (started)
{
if (driver == "hdpvr")
@@ -1362,21 +1315,30 @@ bool MpegRecorder::StartEncoding(int fd)
LOG(VB_GENERAL, LOG_WARNING, LOC + "StartEncoding failed" + ENO);
}
- return started;
+ if (_device_read_buffer)
+ {
+ _device_read_buffer->Reset(videodevice.toAscii().constData(), readfd);
+ _device_read_buffer->Start();
+ }
+
+ return true;
}
-bool MpegRecorder::StopEncoding(int fd)
+void MpegRecorder::StopEncoding(void)
{
QMutexLocker locker(&start_stop_encoding_lock);
+ LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
+
+ if (readfd < 0)
+ return;
+
struct v4l2_encoder_cmd command;
memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
command.cmd = V4L2_ENC_CMD_STOP;
command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
- LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
-
- bool stopped = 0 == ioctl(fd, VIDIOC_ENCODER_CMD, &command);
+ bool stopped = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
if (stopped)
{
LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
@@ -1393,7 +1355,15 @@ bool MpegRecorder::StopEncoding(int fd)
LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
}
- return stopped;
+ if (_device_read_buffer && _device_read_buffer->IsRunning())
+ {
+ usleep(20 * 1000); // allow last bits of data through..
+ _device_read_buffer->Stop();
+ }
+
+ // close the fd so streamoff/streamon work in V4LChannel
+ close(readfd);
+ readfd = -1;
}
void MpegRecorder::SetStreamData(void)
@@ -68,8 +68,8 @@ class MpegRecorder : public V4LRecorder,
uint GetFilteredAudioBitRate(uint audio_layer) const;
void RestartEncoding(void);
- bool StartEncoding(int fd);
- bool StopEncoding(int fd);
+ bool StartEncoding(void);
+ void StopEncoding(void);
void SetBitrate(int bitrate, int maxbitrate, const QString & reason);
void HandleResolutionChanges(void);

0 comments on commit f81f712

Please sign in to comment.