libtriple: avoid race conditions in cVideo::ShowPicture

ShowPicture() and Stop() were racing, and the calling order from
neutrino seems to be not necessarily "correct". With gcc-4.8 /
glibc-2.16 binaries it happened that on switching to radio mode,
ShowPicture() was called and then the Stop() from stopping video
playback happened. This broke the stillpicture. Fix by adding more
locks and explicitly bailing out of Stop() if a picture is shown.
This commit is contained in:
Stefan Seyfried
2013-12-02 00:58:37 +01:00
parent f403e3b3e2
commit e4dba8b30e
2 changed files with 23 additions and 1 deletions

View File

@@ -44,6 +44,7 @@ public:
video_play_state_t playstate;
vidDispMode_t croppingMode;
vidOutFmt_t outputformat;
bool pic_shown;
int scartvoltage;
int z[2]; /* zoomvalue for 4:3 (0) and 16:9 (1) in percent */
int *zoomvalue;

View File

@@ -136,6 +136,7 @@ VDec::VDec(void)
close(blankfd);
}
video_standby = 0;
pic_shown = false;
noscart = (getenv("TRIPLE_NOSCART") != NULL);
if (noscart)
lt_info("%s TRIPLE_NOSCART variable prevents SCART switching\n", __FUNCTION__);
@@ -341,6 +342,14 @@ int cVideo::Stop(bool blank)
int VDec::Stop(bool blank)
{
lt_debug("%s(%d)\n", __FUNCTION__, blank);
bool stillp = false;
pthread_mutex_lock(&stillp_mutex);
stillp = pic_shown;
pthread_mutex_unlock(&stillp_mutex);
/* do not stop the stillpic */
if (stillp)
return -1;
if (blank)
{
playstate = VIDEO_STOPPED;
@@ -369,6 +378,9 @@ int VDec::setBlank(void)
VIDEOINFO v;
BUFINFO buf;
pthread_mutex_lock(&stillp_mutex);
/* dont blank if a picture is shown */
if (pic_shown)
goto out;
memset(&v, 0, sizeof(v));
ioctl(fd, MPEG_VID_GET_V_INFO, &v);
@@ -519,10 +531,16 @@ void VDec::ShowPicture(const char * fname)
lt_info("%s short read (%m)\n", __FUNCTION__);
else
{
pic_shown = true;
BUFINFO buf;
buf.ulLen = st.st_size;
buf.ulStartAdrOff = (int)data;
Stop(false);
/* Stop() wants to locks stillp_mutex, so don't call that */
// Stop(false);
playstate = VIDEO_FREEZED;
fop(ioctl, MPEG_VID_FREEZE);
/* writing twice seems to be more reliable */
fop(ioctl, MPEG_VID_STILLP_WRITE, &buf);
fop(ioctl, MPEG_VID_STILLP_WRITE, &buf);
}
free(data);
@@ -564,7 +582,10 @@ void cVideo::StopPicture()
void VDec::StopPicture()
{
lt_debug("%s\n", __FUNCTION__);
pthread_mutex_lock(&stillp_mutex);
fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX);
pic_shown = false;
pthread_mutex_unlock(&stillp_mutex);
}
void cVideo::Standby(unsigned int bOn)