From eb6b33922e71dd40161ce5d558e4e5eab4953467 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Sun, 13 Jan 2013 21:52:36 +0000 Subject: [PATCH] timeshift: add abs seek and proper 90kHz/1MHz conversions. --- src/htsp_server.c | 26 +++++++++++++------------- src/timeshift.c | 8 ++++++++ src/timeshift/private.h | 1 + src/timeshift/timeshift_reader.c | 16 ++++++++++++++-- src/tvheadend.h | 5 +++++ 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/htsp_server.c b/src/htsp_server.c index fe135815..75b15d41 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -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); diff --git a/src/timeshift.c b/src/timeshift.c index b068c40f..34b21040 100644 --- a/src/timeshift.c +++ b/src/timeshift.c @@ -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); diff --git a/src/timeshift/private.h b/src/timeshift/private.h index 655b2539..480f334e 100644 --- a/src/timeshift/private.h +++ b/src/timeshift/private.h @@ -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, diff --git a/src/timeshift/timeshift_reader.c b/src/timeshift/timeshift_reader.c index 7430c6f5..87a08205 100644 --- a/src/timeshift/timeshift_reader.c +++ b/src/timeshift/timeshift_reader.c @@ -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 */ diff --git a/src/tvheadend.h b/src/tvheadend.h index 0df50c13..d8446be7 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -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);