timeshift: add abs seek and proper 90kHz/1MHz conversions.

This commit is contained in:
Adam Sutton 2013-01-13 21:52:36 +00:00
parent 54e7e2ce5e
commit eb6b33922e
5 changed files with 41 additions and 15 deletions

View file

@ -1402,18 +1402,6 @@ htsp_method_skip(htsp_connection_t *htsp, htsmsg_t *in)
if(htsmsg_get_u32(in, "subscriptionId", &sid))
return htsp_error("Missing argument 'subscriptionId'");
abs = htsmsg_get_u32_or_default(in, "absolute", 0);
if(!htsmsg_get_s64(in, "time", &s64)) {
skip.type = abs ? SMT_SKIP_ABS_TIME : SMT_SKIP_REL_TIME;
skip.time = s64;
} else if (!htsmsg_get_s64(in, "size", &s64)) {
skip.type = abs ? SMT_SKIP_ABS_SIZE : SMT_SKIP_REL_SIZE;
skip.size = s64;
} else {
return htsp_error("Missing argument 'time' or 'size'");
}
LIST_FOREACH(hs, &htsp->htsp_subscriptions, hs_link)
if(hs->hs_sid == sid)
break;
@ -1421,6 +1409,18 @@ htsp_method_skip(htsp_connection_t *htsp, htsmsg_t *in)
if(hs == NULL)
return htsp_error("Requested subscription does not exist");
abs = htsmsg_get_u32_or_default(in, "absolute", 0);
if(!htsmsg_get_s64(in, "time", &s64)) {
skip.type = abs ? SMT_SKIP_ABS_TIME : SMT_SKIP_REL_TIME;
skip.time = hs->hs_90khz ? s64 : ts_rescale_i(s64, 1000000);
} else if (!htsmsg_get_s64(in, "size", &s64)) {
skip.type = abs ? SMT_SKIP_ABS_SIZE : SMT_SKIP_REL_SIZE;
skip.size = s64;
} else {
return htsp_error("Missing argument 'time' or 'size'");
}
subscription_set_skip(hs->hs_s, &skip);
htsp_reply(htsp, in, htsmsg_create_map());
@ -2445,7 +2445,7 @@ htsp_subscription_skip(htsp_subscription_t *hs, streaming_skip_t *skip)
if (skip->type == SMT_SKIP_ERROR)
htsmsg_add_u32(m, "error", 1);
else if (skip->type == SMT_SKIP_ABS_TIME || skip->type == SMT_SKIP_REL_TIME)
htsmsg_add_s64(m, "time", skip->time);
htsmsg_add_s64(m, "time", hs->hs_90khz ? skip->time : ts_rescale(skip->time, 1000000));
else if (skip->type == SMT_SKIP_ABS_SIZE || skip->type == SMT_SKIP_REL_SIZE)
htsmsg_add_s64(m, "size", skip->size);
htsp_send(hs->hs_htsp, m, NULL, &hs->hs_q, 0);

View file

@ -146,6 +146,13 @@ static void timeshift_input
(sm->sm_type == SMT_STOP && sm->sm_code == 0))
exit = 1;
/* Record (one-off) PTS delta */
if (sm->sm_type == SMT_PACKET && ts->pts_delta == PTS_UNSET) {
th_pkt_t *pkt = sm->sm_data;
if (pkt->pkt_pts != PTS_UNSET)
ts->pts_delta = getmonoclock() - ts_rescale(pkt->pkt_pts, 1000000);
}
/* Buffer to disk */
if ((ts->state > TS_LIVE) || (!ts->ondemand && (ts->state == TS_LIVE))) {
sm->sm_time = getmonoclock();
@ -230,6 +237,7 @@ streaming_target_t *timeshift_create
ts->vididx = -1;
ts->id = timeshift_index;
ts->ondemand = timeshift_ondemand;
ts->pts_delta = PTS_UNSET;
pthread_mutex_init(&ts->rdwr_mutex, NULL);
pthread_mutex_init(&ts->state_mutex, NULL);

View file

@ -81,6 +81,7 @@ typedef struct timeshift {
char *path; ///< Directory containing buffer
time_t max_time; ///< Maximum period to shift
int ondemand; ///< Whether this is an on-demand timeshift
int64_t pts_delta; ///< Delta between system clock and PTS
enum {
TS_INIT,

View file

@ -382,12 +382,23 @@ void *timeshift_reader ( void *p )
} else if (ctrl->sm_type == SMT_SKIP) {
skip = ctrl->sm_data;
switch (skip->type) {
case SMT_SKIP_ABS_TIME:
if (ts->pts_delta == PTS_UNSET) {
tvhlog(LOG_ERR, "timeshift", "ts %d abs skip not possible no PTS delta", ts->id);
skip = NULL;
break;
}
/* -fallthrough */
case SMT_SKIP_REL_TIME:
tvhlog(LOG_DEBUG, "timeshift", "ts %d skip %"PRId64" requested", ts->id, skip->time);
/* Convert */
skip_time = ts_rescale(skip->time, 1000000);
skip_time += (skip->type == SMT_SKIP_ABS_TIME) ? ts->pts_delta : last_time;
/* Must handle live playback case */
if (ts->state == TS_LIVE) {
if (skip->time < 0) {
if (skip_time < now) {
pthread_mutex_lock(&ts->rdwr_mutex);
if ((cur_file = timeshift_filemgr_get(ts, ts->ondemand))) {
ts->state = TS_PLAY;
@ -408,9 +419,10 @@ void *timeshift_reader ( void *p )
/* OK */
if (skip) {
/* Adjust time */
play_time = now;
pause_time = skip_time = last_time + skip->time;
pause_time = skip_time;
tsi = NULL;
/* Clear existing packet */

View file

@ -526,6 +526,11 @@ static inline int64_t ts_rescale(int64_t ts, int tb)
return (ts * tb ) / 90000LL;
}
static inline int64_t ts_rescale_i(int64_t ts, int tb)
{
return (ts * 90000LL) / tb;
}
void sbuf_init(sbuf_t *sb);
void sbuf_free(sbuf_t *sb);