mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
libtriple: improve cPlayback()
* avoid race conditions by using a mutex to protect curr_pos, fixing artefacts during timeshift playback * make GetPosition() cheaper by interpolating end_pts and only fetching the "real" end_pts after the file has grown by 10MB
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
#include "dmx_td.h"
|
#include "dmx_td.h"
|
||||||
#include "audio_td.h"
|
#include "audio_td.h"
|
||||||
#include "video_td.h"
|
#include "video_td.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
|
||||||
#include <tddevices.h>
|
#include <tddevices.h>
|
||||||
#define DVR "/dev/" DEVICE_NAME_PVR
|
#define DVR "/dev/" DEVICE_NAME_PVR
|
||||||
@@ -30,6 +31,8 @@ static void playthread_cleanup_handler(void *);
|
|||||||
static pthread_cond_t playback_ready_cond = PTHREAD_COND_INITIALIZER;
|
static pthread_cond_t playback_ready_cond = PTHREAD_COND_INITIALIZER;
|
||||||
static pthread_mutex_t playback_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t playback_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static pthread_mutex_t currpos_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
static int dvrfd = -1;
|
static int dvrfd = -1;
|
||||||
static int streamtype;
|
static int streamtype;
|
||||||
|
|
||||||
@@ -77,6 +80,7 @@ bool cPlayback::Open(playmode_t mode)
|
|||||||
filetype = FILETYPE_TS;
|
filetype = FILETYPE_TS;
|
||||||
playback_speed = 0;
|
playback_speed = 0;
|
||||||
last_size = 0;
|
last_size = 0;
|
||||||
|
_pts_end = 0;
|
||||||
numpida = 0;
|
numpida = 0;
|
||||||
memset(&apids, 0, sizeof(apids));
|
memset(&apids, 0, sizeof(apids));
|
||||||
memset(&ac3flags, 0, sizeof(ac3flags));
|
memset(&ac3flags, 0, sizeof(ac3flags));
|
||||||
@@ -441,11 +445,16 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
|||||||
if (filetype == FILETYPE_TS && filelist.size() == 1)
|
if (filetype == FILETYPE_TS && filelist.size() == 1)
|
||||||
{
|
{
|
||||||
off_t tmppos = currsize - PESBUF_SIZE;
|
off_t tmppos = currsize - PESBUF_SIZE;
|
||||||
if (currsize != last_size && tmppos > 0)
|
if (currsize > last_size && (currsize - last_size) < 10485760 &&
|
||||||
|
bytes_per_second > 0 && _pts_end > 0)
|
||||||
{
|
{
|
||||||
update = true;
|
/* guess the current endpts... */
|
||||||
/* file size has changed => update endpts */
|
tmppts = (currsize - last_size) * 90000 / bytes_per_second;
|
||||||
last_size = currsize;
|
pts_end = _pts_end + tmppts;
|
||||||
|
}
|
||||||
|
else if (currsize != last_size && tmppos > 0)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&currpos_mutex);
|
||||||
off_t oldpos = curr_pos;
|
off_t oldpos = curr_pos;
|
||||||
ssize_t n, r;
|
ssize_t n, r;
|
||||||
int s;
|
int s;
|
||||||
@@ -462,11 +471,16 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
|||||||
{
|
{
|
||||||
DBG("n: %d s: %d endpts %lld size: %lld\n", n, s, tmppts, currsize);
|
DBG("n: %d s: %d endpts %lld size: %lld\n", n, s, tmppts, currsize);
|
||||||
pts_end = tmppts;
|
pts_end = tmppts;
|
||||||
|
_pts_end = tmppts;
|
||||||
|
update = true;
|
||||||
|
/* file size has changed => update endpts */
|
||||||
|
last_size = currsize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mf_lseek(oldpos);
|
mf_lseek(oldpos);
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pts_end != -1 && pts_start > pts_end) /* should trigger only once ;) */
|
if (pts_end != -1 && pts_start > pts_end) /* should trigger only once ;) */
|
||||||
@@ -480,10 +494,11 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
|||||||
{
|
{
|
||||||
position = tmppts / 90;
|
position = tmppts / 90;
|
||||||
duration = (pts_end - pts_start) / 90;
|
duration = (pts_end - pts_start) / 90;
|
||||||
if (update && duration >= 1000)
|
if (update && duration >= 4000)
|
||||||
{
|
{
|
||||||
bytes_per_second = currsize / (duration / 1000);
|
bytes_per_second = currsize / (duration / 1000);
|
||||||
INFO("updated bps: %lld size: %lld duration %d\n", bytes_per_second, currsize, duration);
|
lt_debug("cPlayback:%s: updated bps: %lld size: %lld duration %d\n",
|
||||||
|
__FUNCTION__, bytes_per_second, currsize, duration);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -786,6 +801,7 @@ ssize_t cPlayback::read_ts()
|
|||||||
int n, skipped = 0;
|
int n, skipped = 0;
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
bool eof = true;
|
bool eof = true;
|
||||||
|
pthread_mutex_lock(&currpos_mutex);
|
||||||
while (toread > 0)
|
while (toread > 0)
|
||||||
{
|
{
|
||||||
ssize_t done = 0;
|
ssize_t done = 0;
|
||||||
@@ -801,6 +817,7 @@ ssize_t cPlayback::read_ts()
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
INFO("failed: %m\n");
|
INFO("failed: %m\n");
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (ret == 0 && eof)
|
if (ret == 0 && eof)
|
||||||
@@ -815,6 +832,7 @@ ssize_t cPlayback::read_ts()
|
|||||||
INFO("out of sync: %d\n", sync);
|
INFO("out of sync: %d\n", sync);
|
||||||
if (sync < 0)
|
if (sync < 0)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memmove(pesbuf, pesbuf + sync, ret - sync);
|
memmove(pesbuf, pesbuf + sync, ret - sync);
|
||||||
@@ -861,11 +879,13 @@ ssize_t cPlayback::read_ts()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
if (eof)
|
if (eof)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&currpos_mutex);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
ret = read(in_fd, inbuf + inbuf_pos, toread);
|
ret = read(in_fd, inbuf + inbuf_pos, toread);
|
||||||
@@ -877,15 +897,16 @@ ssize_t cPlayback::read_ts()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret <= 0)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
|
if (ret < 0)
|
||||||
INFO("failed: %m\n");
|
INFO("failed: %m\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (ret == 0)
|
|
||||||
return ret;
|
|
||||||
inbuf_pos += ret;
|
inbuf_pos += ret;
|
||||||
curr_pos += ret;
|
curr_pos += ret;
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
|
|
||||||
sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync);
|
sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync);
|
||||||
if (sync < 0)
|
if (sync < 0)
|
||||||
@@ -1002,6 +1023,7 @@ ssize_t cPlayback::read_mpeg()
|
|||||||
INFO("adjusting toread to %d due to inbuf full (old: %zd)\n", INBUF_SIZE - inbuf_pos, toread);
|
INFO("adjusting toread to %d due to inbuf full (old: %zd)\n", INBUF_SIZE - inbuf_pos, toread);
|
||||||
toread = INBUF_SIZE - inbuf_pos;
|
toread = INBUF_SIZE - inbuf_pos;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_lock(&currpos_mutex);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
ret = read(in_fd, pesbuf + pesbuf_pos, toread);
|
ret = read(in_fd, pesbuf + pesbuf_pos, toread);
|
||||||
@@ -1015,11 +1037,13 @@ ssize_t cPlayback::read_mpeg()
|
|||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
INFO("failed: %m, pesbuf_pos: %zd, toread: %zd\n", pesbuf_pos, toread);
|
INFO("failed: %m, pesbuf_pos: %zd, toread: %zd\n", pesbuf_pos, toread);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pesbuf_pos += ret;
|
pesbuf_pos += ret;
|
||||||
curr_pos += ret;
|
curr_pos += ret;
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -1232,6 +1256,7 @@ off_t cPlayback::mp_seekSync(off_t pos)
|
|||||||
off_t ret;
|
off_t ret;
|
||||||
uint8_t pkt[1024];
|
uint8_t pkt[1024];
|
||||||
|
|
||||||
|
pthread_mutex_lock(&currpos_mutex);
|
||||||
ret = mf_lseek(npos);
|
ret = mf_lseek(npos);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
INFO("lseek ret < 0 (%m)\n");
|
INFO("lseek ret < 0 (%m)\n");
|
||||||
@@ -1277,6 +1302,7 @@ off_t cPlayback::mp_seekSync(off_t pos)
|
|||||||
npos += s;
|
npos += s;
|
||||||
INFO("sync after %lld\n", npos - pos);
|
INFO("sync after %lld\n", npos - pos);
|
||||||
ret = mf_lseek(npos);
|
ret = mf_lseek(npos);
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
INFO("lseek ret < 0 (%m)\n");
|
INFO("lseek ret < 0 (%m)\n");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1285,7 +1311,9 @@ off_t cPlayback::mp_seekSync(off_t pos)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
INFO("could not sync to PES offset: %d r: %zd\n", offset, r);
|
INFO("could not sync to PES offset: %d r: %zd\n", offset, r);
|
||||||
return mf_lseek(pos);
|
ret = mf_lseek(pos);
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: use bigger buffer here, too and handle EOF / next splitfile */
|
/* TODO: use bigger buffer here, too and handle EOF / next splitfile */
|
||||||
@@ -1301,6 +1329,7 @@ off_t cPlayback::mp_seekSync(off_t pos)
|
|||||||
if(pkt[188-1] == 0x47)
|
if(pkt[188-1] == 0x47)
|
||||||
{
|
{
|
||||||
ret = mf_lseek(npos - 1); // assume sync ok
|
ret = mf_lseek(npos - 1); // assume sync ok
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
INFO("lseek ret < 0 (%m)\n");
|
INFO("lseek ret < 0 (%m)\n");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1320,7 +1349,9 @@ off_t cPlayback::mp_seekSync(off_t pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-- on error stay on actual position --
|
//-- on error stay on actual position --
|
||||||
return mf_lseek(pos);
|
ret = mf_lseek(pos);
|
||||||
|
pthread_mutex_unlock(&currpos_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sync_ts(uint8_t *p, int len)
|
static int sync_ts(uint8_t *p, int len)
|
||||||
|
@@ -77,6 +77,7 @@ class cPlayback
|
|||||||
|
|
||||||
int64_t pts_start;
|
int64_t pts_start;
|
||||||
int64_t pts_end;
|
int64_t pts_end;
|
||||||
|
int64_t _pts_end; /* last good endpts */
|
||||||
int64_t pts_curr;
|
int64_t pts_curr;
|
||||||
int64_t get_pts(uint8_t *p, bool pes, int bufsize);
|
int64_t get_pts(uint8_t *p, bool pes, int bufsize);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user