if(htsmsg_get_u32(in, "subscriptionId", &sid))
return htsp_error("Missing argument 'subscriptionId'");
+ LIST_FOREACH(hs, &htsp->htsp_subscriptions, hs_link)
+ if(hs->hs_sid == sid)
+ break;
+
+ 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 = s64;
+ 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;
return htsp_error("Missing argument 'time' or 'size'");
}
- LIST_FOREACH(hs, &htsp->htsp_subscriptions, hs_link)
- if(hs->hs_sid == sid)
- break;
-
- if(hs == NULL)
- return htsp_error("Requested subscription does not exist");
-
subscription_set_skip(hs->hs_s, &skip);
htsp_reply(htsp, in, htsmsg_create_map());
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);
(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();
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);
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,
} 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;
/* 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 */
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);