]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
timeshift: add abs seek and proper 90kHz/1MHz conversions.
authorAdam Sutton <dev@adamsutton.me.uk>
Sun, 13 Jan 2013 21:52:36 +0000 (21:52 +0000)
committerAdam Sutton <dev@adamsutton.me.uk>
Mon, 14 Jan 2013 13:18:46 +0000 (13:18 +0000)
src/htsp_server.c
src/timeshift.c
src/timeshift/private.h
src/timeshift/timeshift_reader.c
src/tvheadend.h

index fe13581555b53d34225482418eaf4e3677c4239a..75b15d41253d488e25f0d8645b6837f121ee4a20 100644 (file)
@@ -1402,11 +1402,18 @@ htsp_method_skip(htsp_connection_t *htsp, htsmsg_t *in)
   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;
@@ -1414,13 +1421,6 @@ htsp_method_skip(htsp_connection_t *htsp, htsmsg_t *in)
     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());
@@ -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);
index b068c40f7359710026a85a850b0964aea1e04af6..34b21040e83d716c1c270a5bf47bd9231325b33e 100644 (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);
 
index 655b2539e57a68567a4b752d5c0f2468e763f1a2..480f334e695bcfc23e4feaf7f5a37b279feb8094 100644 (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,
index 7430c6f55c2fea5c36c0a284deccda0af05a7fb5..87a082052998367987cad861aa70b313d05b82f4 100644 (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 */
index 0df50c13a4e68d3ec2e5d307684840a1b5010aaa..d8446be73cbe321f975d114bb9dd427f6db4b888 100644 (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);