]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Remove per-channel remote timeshift implementation (#2009)
authorCopilot <198982749+Copilot@users.noreply.github.com>
Mon, 8 Dec 2025 21:05:29 +0000 (22:05 +0100)
committerGitHub <noreply@github.com>
Mon, 8 Dec 2025 21:05:29 +0000 (22:05 +0100)
.gitignore
src/channels.c
src/channels.h
src/htsp_server.c
src/input/mpegts/iptv/iptv_private.h
src/input/mpegts/iptv/iptv_rtsp.c
src/profile.c
src/profile.h
src/rtsp.c

index 1798f9ce5a1dd1eb4d9e12ade40a8ab1b7441491..f0a137c6fe84d895b808f6aac6cf4997e7403096 100644 (file)
@@ -62,3 +62,4 @@ Thumbs.db
 Desktop.ini
 #macOS files
 .DS_Store
+_codeql_detected_source_root
index d06eacb23d265d6f849cce7eef2dd8b4d5b50450..521a6e0f5b8664a81d3006d029b0e0460ab2a721 100644 (file)
@@ -542,16 +542,6 @@ const idclass_t channel_class = {
       .list     = channel_class_epg_running_list,
       .opts     = PO_EXPERT | PO_DOC_NLIST,
     },
-#if ENABLE_TIMESHIFT
-    {
-      .type     = PT_BOOL,
-      .id       = "remote_timeshift",
-      .name     = N_("Remote timeshift"),
-      .desc     = N_("Pass timeshift commands to a remote RTSP server"),
-      .off      = offsetof(channel_t, ch_remote_timeshift),
-      .opts     = PO_ADVANCED,
-    },
-#endif
     {
       .type     = PT_STR,
       .islist   = 1,
index 268e2fa8176c3843a628fd0a5520adf35c076497..7b377487d5baa4940602554f8b5c0c10fd578837 100644 (file)
@@ -82,7 +82,6 @@ typedef struct channel
   int                   ch_dvr_extra_time_pre;
   int                   ch_dvr_extra_time_post;
   int                   ch_epg_running;
-  int                   ch_remote_timeshift;
   LIST_HEAD(, dvr_entry)         ch_dvrs;
   LIST_HEAD(, dvr_autorec_entry) ch_autorecs;
   LIST_HEAD(, dvr_timerec_entry) ch_timerecs;
index 2b7abd3691867521de94c5c48a9ca5f544ce5843..5ca20a65fe57b6d96917c87e2d8f916b474e0a68 100644 (file)
@@ -2654,14 +2654,10 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
   profile_id = htsmsg_get_str(in, "profile");
 
 #if ENABLE_TIMESHIFT
-  if(ch->ch_remote_timeshift) {
-    timeshiftPeriod = ~0;
-  } else {
-    if (timeshift_conf.enabled) {
-      timeshiftPeriod = htsmsg_get_u32_or_default(in, "timeshiftPeriod", 0);
-      if (!timeshift_conf.unlimited_period)
-        timeshiftPeriod = MIN(timeshiftPeriod, timeshift_conf.max_period * 60);
-    }
+  if (timeshift_conf.enabled) {
+    timeshiftPeriod = htsmsg_get_u32_or_default(in, "timeshiftPeriod", 0);
+    if (!timeshift_conf.unlimited_period)
+      timeshiftPeriod = MIN(timeshiftPeriod, timeshift_conf.max_period * 60);
   }
 #endif
 
@@ -2679,24 +2675,19 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
   streaming_target_init(&hs->hs_input, &htsp_streaming_input_ops, hs, 0);
 
 #if ENABLE_TIMESHIFT
-  if (ch->ch_remote_timeshift) {
-    tvhdebug(LS_HTSP, "using remote timeshift (RTSP)");
-  } else {
-    if (timeshiftPeriod != 0) {
-      if (timeshiftPeriod == ~0)
-        tvhdebug(LS_HTSP, "using timeshift buffer (unlimited)");
-      else
-        tvhdebug(LS_HTSP, "using timeshift buffer (%u mins)",
-            timeshiftPeriod / 60);
-    }
+  if (timeshiftPeriod != 0) {
+    if (timeshiftPeriod == ~0)
+      tvhdebug(LS_HTSP, "using timeshift buffer (unlimited)");
+    else
+      tvhdebug(LS_HTSP, "using timeshift buffer (%u mins)",
+          timeshiftPeriod / 60);
   }
 #endif
 
   pro = profile_find_by_list(htsp->htsp_granted_access->aa_profiles, profile_id,
                              "htsp", SUBSCRIPTION_PACKET | SUBSCRIPTION_HTSP);
   profile_chain_init(&hs->hs_prch, pro, ch, 1);
-  if (profile_chain_work(&hs->hs_prch, &hs->hs_input, timeshiftPeriod, ch->ch_remote_timeshift ?
-      PROFILE_WORK_REMOTE_TS : PROFILE_WORK_NONE)) {
+  if (profile_chain_work(&hs->hs_prch, &hs->hs_input, timeshiftPeriod)) {
     tvherror(LS_HTSP, "unable to create profile chain '%s'", profile_get_name(pro));
     profile_chain_close(&hs->hs_prch);
     free(hs);
@@ -2720,12 +2711,8 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
     htsmsg_add_u32(rep, "weight", hs->hs_s->ths_weight >= 0 ? hs->hs_s->ths_weight : 0);
 
 #if ENABLE_TIMESHIFT
-  if (ch->ch_remote_timeshift) {
+  if (timeshiftPeriod)
     htsmsg_add_u32(rep, "timeshiftPeriod", timeshiftPeriod);
-  } else {
-    if (timeshiftPeriod)
-      htsmsg_add_u32(rep, "timeshiftPeriod", timeshiftPeriod);
-  }
 #endif
 
   htsp_reply(htsp, in, rep);
index c5dcf13670f605132fc8b200174bc1058d1b9e30..314833e0d74c172faa2c1d29f159a87e9db7908e 100644 (file)
@@ -239,23 +239,6 @@ ssize_t iptv_rtp_read(iptv_mux_t *im, void (*pkt_cb)(iptv_mux_t *im, uint8_t *bu
 
 void iptv_input_unpause ( void *aux );
 
-struct rtsp_st {
-  // Note: input MUST BE FIRST in struct
-  streaming_target_t          input;      ///< Input source
-  streaming_target_t          *output;    ///< Output dest
-  streaming_target_t          *tsfix;
-  pthread_t                   st_thread;
-  volatile int                run;
-  volatile int                rtsp_input_start;
-  iptv_mux_t *im;
-};
-
-typedef struct rtsp_st rtsp_st_t;
-#if ENABLE_TIMESHIFT
-void *rtsp_status_thread(void *p) ;
-streaming_target_t* rtsp_st_create(streaming_target_t *out, profile_chain_t *prch);
-void rtsp_st_destroy(streaming_target_t *st);
-#endif
 #endif /* __IPTV_PRIVATE_H__ */
 
 /******************************************************************************
index ec3c3db65d5c0cfc2f7b256ce3dcb5b3b18e69fd..9e702664ac9b9a299d73d4a63008aeeebd1085d5 100644 (file)
@@ -411,154 +411,6 @@ iptv_rtsp_read ( iptv_input_t *mi, iptv_mux_t *im )
   return r;
 }
 
-/*
- * Send the status message
- */
-#if ENABLE_TIMESHIFT
-static void rtsp_timeshift_fill_status(rtsp_st_t *ts, rtsp_priv_t *rp,
-    timeshift_status_t *status) {
-  int64_t start, end, current;
-
-  if (rp == NULL) {
-    start = 0;
-    end = 3600;
-    current = 0;
-  } else {
-    start = 0;
-    end = rp->range_end - rp->range_start;
-    current = rp->position - rp->range_start;
-  }
-  status->full = 0;
-
-  tvhdebug(LS_TIMESHIFT,
-      "remote ts status start %"PRId64" end %"PRId64 " current %"PRId64, start, end,
-      current);
-
-  status->shift = ts_rescale_inv(current, 1);
-  status->pts_start = ts_rescale_inv(start, 1);
-  status->pts_end = ts_rescale_inv(end, 1);
-}
-
-static void rtsp_timeshift_status
-  ( rtsp_st_t *pd, rtsp_priv_t *rp )
-{
-  streaming_message_t *tsm, *tsm2;
-  timeshift_status_t *status;
-
-  status = calloc(1, sizeof(timeshift_status_t));
-  rtsp_timeshift_fill_status(pd, rp, status);
-  tsm = streaming_msg_create_data(SMT_TIMESHIFT_STATUS, status);
-  tsm2 = streaming_msg_clone(tsm);
-  streaming_target_deliver2(pd->output, tsm);
-  streaming_target_deliver2(pd->tsfix, tsm2);
-}
-
-void *rtsp_status_thread(void *p) {
-  int64_t mono_now, mono_last_status = 0;
-  rtsp_st_t *pd = p;
-  rtsp_priv_t *rp;
-
-  while (pd->run) {
-    mono_now  = getfastmonoclock();
-    if(pd->im == NULL)
-      continue;
-    rp = (rtsp_priv_t*) pd->im->im_data;
-    if(rp == NULL || !pd->rtsp_input_start)
-      continue;
-    if (mono_now >= (mono_last_status + sec2mono(1))) {
-      // In case no buffer updates available assume the buffer is being filled
-      if(rp->hc && rp->hc->hc_rtsp_keep_alive_cmd != RTSP_CMD_DESCRIBE)
-        rp->range_end++;
-      rtsp_timeshift_status(pd, rp);
-      mono_last_status = mono_now;
-    }
-  }
-  return NULL;
-}
-
-static void rtsp_input(void *opaque, streaming_message_t *sm) {
-  rtsp_st_t *pd = (rtsp_st_t*) opaque;
-  iptv_mux_t *mux;
-  streaming_skip_t *data;
-  rtsp_priv_t *rp;
-
-  if(pd == NULL || sm == NULL)
-    return;
-
-  switch (sm->sm_type) {
-  case SMT_GRACE:
-    if (sm->sm_s != NULL)
-      pd->im = (iptv_mux_t*) ((mpegts_service_t*) sm->sm_s)->s_dvb_mux;
-    streaming_target_deliver2(pd->output, sm);
-    break;
-  case SMT_START:
-    pd->rtsp_input_start = 1;
-    streaming_target_deliver2(pd->output, sm);
-    break;
-  case SMT_SKIP:
-    mux = (iptv_mux_t*) pd->im;
-    if (mux == NULL || mux->im_data == NULL)
-      break;
-    rp = (rtsp_priv_t*) mux->im_data;
-    if (rp->start_position == 0)
-      rp->start_position = rp->hc->hc_rtsp_stream_start;
-    rtsp_pause(rp->hc, rp->path, rp->query);
-    mux->mm_iptv_rtp_seq = -1;
-    data = (streaming_skip_t*) sm->sm_data;
-    rtsp_set_position(rp->hc,
-        rp->range_start + ts_rescale(data->time, 1));
-    tvhinfo(LS_IPTV, "rtsp: skip: %" PRItime_t " + %" PRId64, rp->range_start,
-        ts_rescale(data->time, 1));
-    streaming_msg_free(sm);
-    break;
-  case SMT_SPEED:
-    mux = (iptv_mux_t*) pd->im;
-    if (mux == NULL || mux->im_data == NULL)
-      break;
-    rp = (rtsp_priv_t*) mux->im_data;
-    tvhinfo(LS_IPTV, "rtsp: set speed: %i", sm->sm_code);
-    if (sm->sm_code == 0) {
-      rtsp_pause(rp->hc, rp->path, rp->query);
-    } else {
-      rtsp_set_speed(rp->hc, sm->sm_code / 100);
-    }
-    streaming_msg_free(sm);
-    break;
-  case SMT_EXIT:
-    pd->run = 0;
-    streaming_target_deliver2(pd->output, sm);
-    break;
-  default:
-    streaming_target_deliver2(pd->output, sm);
-  }
-}
-
-static htsmsg_t*
-rtsp_input_info(void *opaque, htsmsg_t *list) {
-  return list;
-}
-
-static streaming_ops_t rtsp_input_ops =
-{ .st_cb = rtsp_input, .st_info = rtsp_input_info };
-
-streaming_target_t* rtsp_st_create(streaming_target_t *out, profile_chain_t *prch) {
-  rtsp_st_t *h = calloc(1, sizeof(rtsp_st_t));
-
-  h->output = out;
-  h->tsfix = prch->prch_share;
-  h->run = 1;
-  tvh_thread_create(&h->st_thread, NULL, rtsp_status_thread, h, "rtsp-st");
-  streaming_target_init(&h->input, &rtsp_input_ops, h, 0);
-
-  return &h->input;
-}
-
-void rtsp_st_destroy(streaming_target_t *st) {
-  rtsp_st_t *h = (rtsp_st_t*)st;
-  h->run = 0;
-  free(st);
-}
-#endif
 /*
  * Initialise RTSP handler
  */
index 1aa9c57c809a034131110bbfb8e4623f3051e221..7d2277c719d269d4ad8e573854d9738adbe71975 100644 (file)
@@ -1049,11 +1049,11 @@ profile_chain_init(profile_chain_t *prch, profile_t *pro, void *id, int queue)
  */
 int
 profile_chain_work(profile_chain_t *prch, struct streaming_target *dst,
-                   uint32_t timeshift_period, profile_work_flags_t flags)
+                   uint32_t timeshift_period)
 {
   profile_t *pro = prch->prch_pro;
   if (pro && pro->pro_work)
-    return pro->pro_work(prch, dst, timeshift_period, flags);
+    return pro->pro_work(prch, dst, timeshift_period);
   return -1;
 }
 
@@ -1162,12 +1162,6 @@ profile_chain_close(profile_chain_t *prch)
     timeshift_destroy(prch->prch_timeshift);
     prch->prch_timeshift = NULL;
   }
-#if ENABLE_IPTV
-  if(prch->prch_rtsp) {
-    rtsp_st_destroy(prch->prch_rtsp);
-    prch->prch_rtsp = NULL;
-  }
-#endif
 #endif
   if (prch->prch_gh) {
     globalheaders_destroy(prch->prch_gh);
@@ -1219,7 +1213,7 @@ const idclass_t profile_htsp_class =
 static int
 profile_htsp_work(profile_chain_t *prch,
                   streaming_target_t *dst,
-                  uint32_t timeshift_period, profile_work_flags_t flags)
+                  uint32_t timeshift_period)
 {
   profile_sharer_t *prsh;
 
@@ -1232,13 +1226,8 @@ profile_htsp_work(profile_chain_t *prch,
   prch->prch_share = prsh->prsh_tsfix;
 
 #if ENABLE_TIMESHIFT
-#if ENABLE_IPTV
-  if (flags & PROFILE_WORK_REMOTE_TS)
-    dst = prch->prch_rtsp = rtsp_st_create(dst, prch);
-  else
-#endif
-    if (timeshift_period > 0)
-      dst = prch->prch_timeshift = timeshift_create(dst, timeshift_period);
+  if (timeshift_period > 0)
+    dst = prch->prch_timeshift = timeshift_create(dst, timeshift_period);
 #endif
 
   dst = prch->prch_gh = globalheaders_create(dst);
@@ -2006,7 +1995,7 @@ profile_audio_open(profile_chain_t *prch,
   prch->prch_flags = SUBSCRIPTION_PACKET;
   prch->prch_sq.sq_maxsize = qsize;
 
-  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0);
+  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0);
   if (r) {
     profile_chain_close(prch);
     return r;
@@ -2074,7 +2063,7 @@ profile_libav_mpegts_open(profile_chain_t *prch,
   prch->prch_flags = SUBSCRIPTION_PACKET;
   prch->prch_sq.sq_maxsize = qsize;
 
-  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0);
+  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0);
   if (r) {
     profile_chain_close(prch);
     return r;
@@ -2165,7 +2154,7 @@ profile_libav_matroska_open(profile_chain_t *prch,
   prch->prch_flags = SUBSCRIPTION_PACKET;
   prch->prch_sq.sq_maxsize = qsize;
 
-  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0);
+  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0);
   if (r) {
     profile_chain_close(prch);
     return r;
@@ -2228,7 +2217,7 @@ profile_libav_mp4_open(profile_chain_t *prch,
   prch->prch_flags = SUBSCRIPTION_PACKET;
   prch->prch_sq.sq_maxsize = qsize;
 
-  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0);
+  r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0);
   if (r) {
     profile_chain_close(prch);
     return r;
@@ -2684,7 +2673,7 @@ profile_transcode_can_share(profile_chain_t *prch,
 static int
 profile_transcode_work(profile_chain_t *prch,
                        streaming_target_t *dst,
-                       uint32_t timeshift_period, profile_work_flags_t flags)
+                       uint32_t timeshift_period)
 {
   profile_sharer_t *prsh;
   profile_transcode_t *pro = (profile_transcode_t *)prch->prch_pro;
@@ -2797,7 +2786,7 @@ profile_transcode_open(profile_chain_t *prch,
   prch->prch_flags = SUBSCRIPTION_PACKET;
   prch->prch_sq.sq_maxsize = qsize;
 
-  r = profile_transcode_work(prch, &prch->prch_sq.sq_st, 0, 0);
+  r = profile_transcode_work(prch, &prch->prch_sq.sq_st, 0);
   if (r) {
     profile_chain_close(prch);
     return r;
index ac135c4d669c5e316537fe00c5652046c92c78d7..647084e3e64b0a5a29154cf26cbd155efabc6a5c 100644 (file)
@@ -45,10 +45,7 @@ typedef enum {
   PROFILE_SVF_UHD
 } profile_svfilter_t;
 
-typedef enum {
-  PROFILE_WORK_NONE = 0,
-  PROFILE_WORK_REMOTE_TS
-} profile_work_flags_t;
+
 
 struct profile;
 struct muxer;
@@ -99,7 +96,6 @@ typedef struct profile_chain {
   struct streaming_target  *prch_tsfix;
 #if ENABLE_TIMESHIFT
   struct streaming_target  *prch_timeshift;
-  struct streaming_target  *prch_rtsp;
 #endif
   struct streaming_target   prch_input;
   struct streaming_target  *prch_share;
@@ -136,7 +132,7 @@ typedef struct profile {
   void (*pro_conf_changed)(struct profile *pro);
 
   int (*pro_work)(profile_chain_t *prch, struct streaming_target *dst,
-                  uint32_t timeshift_period, profile_work_flags_t flags);
+                  uint32_t timeshift_period);
   int (*pro_reopen)(profile_chain_t *prch, muxer_config_t *m_cfg,
                     muxer_hints_t *hints, int flags);
   int (*pro_open)(profile_chain_t *prch, muxer_config_t *m_cfg,
@@ -182,7 +178,7 @@ static inline void profile_release( profile_t *pro )
   }
 
 int profile_chain_work(profile_chain_t *prch, struct streaming_target *dst,
-                       uint32_t timeshift_period, profile_work_flags_t flags);
+                       uint32_t timeshift_period);
 int profile_chain_reopen(profile_chain_t *prch,
                          muxer_config_t *m_cfg,
                          muxer_hints_t *hints, int flags);
index f4ca839226c40a9b9574e300e1f0e604e423c356..d6244003e17c4d0651df5967566eb89281a62a15 100644 (file)
@@ -287,7 +287,7 @@ int rtsp_describe_decode(http_client_t *hc, const char *buf, size_t len) {
   for (n = 0; n < len; n++) {
     p = buf + n;
     if (strncmp(p, "a=range", 7) == 0) {
-      // Parse remote timeshift buffer info
+      // Parse RTSP range info
       if (strncmp(p + 8, "npt=", 4) == 0) {
         sscanf(p + 8, "npt=%" PRItime_t "-%" PRItime_t, &hc->hc_rtsp_range_start,
             &hc->hc_rtsp_range_end);