Esempio n. 1
0
/*
 * Output packet
 */
static int _timeshift_read
  ( timeshift_t *ts, timeshift_file_t **cur_file,
    streaming_message_t **sm, int *wait )
{
  timeshift_file_t *tsf = *cur_file;
  ssize_t r;
  off_t off, ooff;

  if (tsf) {

    /* Open file */
    if (tsf->rfd < 0 && !tsf->ram) {
      tsf->rfd = open(tsf->path, O_RDONLY);
      tvhtrace("timeshift", "ts %d open file %s (fd %i)", ts->id, tsf->path, tsf->rfd);
      if (tsf->rfd < 0)
        return -1;
    }
    tvhtrace("timeshift", "ts %d seek to %jd (fd %i)", ts->id, tsf->roff, tsf->rfd);
    if (tsf->rfd >= 0)
      if ((off = lseek(tsf->rfd, tsf->roff, SEEK_SET)) != tsf->roff)
        tvherror("timeshift", "seek to %s failed (off %"PRId64" != %"PRId64"): %s",
                 tsf->path, (int64_t)tsf->roff, (int64_t)off, strerror(errno));

    /* Read msg */
    ooff = tsf->roff;
    r = _read_msg(tsf, -1, sm);
    if (r < 0) {
      streaming_message_t *e = streaming_msg_create_code(SMT_STOP, SM_CODE_UNDEFINED_ERROR);
      streaming_target_deliver2(ts->output, e);
      tvhlog(LOG_ERR, "timeshift", "ts %d could not read buffer", ts->id);
      return -1;
    }
#if ENABLE_ANDROID
    tvhtrace("timeshift", "ts %d read msg %p (%ld)", ts->id, *sm, r);  // Android bug, ssize_t is long int
#else
    tvhtrace("timeshift", "ts %d read msg %p (%zd)", ts->id, *sm, r);
#endif

    /* Incomplete */
    if (r == 0) {
      if (tsf->rfd >= 0) {
        tvhtrace("timeshift", "ts %d seek to %jd (fd %i) (incomplete)", ts->id, tsf->roff, tsf->rfd);
        if ((off = lseek(tsf->rfd, ooff, SEEK_SET)) != ooff)
          tvherror("timeshift", "seek to %s failed (off %"PRId64" != %"PRId64"): %s",
                   tsf->path, (int64_t)ooff, (int64_t)off, strerror(errno));
      }
      tsf->roff = ooff;
      return 0;
    }

    /* Special case - EOF */
    if (r == sizeof(size_t) || tsf->roff > tsf->size) {
      if (tsf->rfd >= 0)
        close(tsf->rfd);
      tsf->rfd  = -1;
      pthread_mutex_lock(&ts->rdwr_mutex);
      *cur_file = timeshift_filemgr_next(tsf, NULL, 0);
      pthread_mutex_unlock(&ts->rdwr_mutex);
      tsf->roff = 0; // reset
      *wait     = 0;

    /* Check SMT_START index */
    } else {
      streaming_message_t *ssm = _timeshift_find_sstart(*cur_file, (*sm)->sm_time);
      if (ssm && ssm->sm_data != ts->smt_start) {
        streaming_target_deliver2(ts->output, streaming_msg_clone(ssm));
        if (ts->smt_start)
          streaming_start_unref(ts->smt_start);
        ts->smt_start = ssm->sm_data;
        atomic_add(&ts->smt_start->ss_refcount, 1);
      }
    }
  }
  return 0;
}
Esempio n. 2
0
/*
 * Receive data
 */
static void timeshift_input
  ( void *opaque, streaming_message_t *sm )
{
  int exit = 0;
  timeshift_t *ts = opaque;
  th_pkt_t *pkt = sm->sm_data;

  pthread_mutex_lock(&ts->state_mutex);

  /* Control */
  if (sm->sm_type == SMT_SKIP) {
    if (ts->state >= TS_LIVE)
      timeshift_write_skip(ts->rd_pipe.wr, sm->sm_data);
  } else if (sm->sm_type == SMT_SPEED) {
    if (ts->state >= TS_LIVE)
      timeshift_write_speed(ts->rd_pipe.wr, sm->sm_code);
  }

  else {

    /* Start */
    if (sm->sm_type == SMT_START && ts->state == TS_INIT) {
      ts->state  = TS_LIVE;
    }

    if (sm->sm_type == SMT_PACKET) {
      tvhtrace("timeshift",
               "ts %d pkt in  - stream %d type %c pts %10"PRId64
               " dts %10"PRId64" dur %10d len %zu",
               ts->id,
               pkt->pkt_componentindex,
               pkt_frametype_to_char(pkt->pkt_frametype),
               ts_rescale(pkt->pkt_pts, 1000000),
               ts_rescale(pkt->pkt_dts, 1000000),
               pkt->pkt_duration,
               pktbuf_len(pkt->pkt_payload));
    }

    /* Pass-thru */
    if (ts->state <= TS_LIVE) {
      if (sm->sm_type == SMT_START) {
        if (ts->smt_start)
          streaming_start_unref(ts->smt_start);
        ts->smt_start = sm->sm_data;
        atomic_add(&ts->smt_start->ss_refcount, 1);
      }
      streaming_target_deliver2(ts->output, streaming_msg_clone(sm));
    }

    /* Check for exit */
    if (sm->sm_type == SMT_EXIT ||
        (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) {
      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();
      if (sm->sm_type == SMT_PACKET) {
        tvhtrace("timeshift",
                 "ts %d pkt buf - stream %d type %c pts %10"PRId64
                 " dts %10"PRId64" dur %10d len %zu",
                 ts->id,
                 pkt->pkt_componentindex,
                 pkt_frametype_to_char(pkt->pkt_frametype),
                 ts_rescale(pkt->pkt_pts, 1000000),
                 ts_rescale(pkt->pkt_dts, 1000000),
                 pkt->pkt_duration,
                 pktbuf_len(pkt->pkt_payload));
      }
      streaming_target_deliver2(&ts->wr_queue.sq_st, sm);
    } else
      streaming_msg_free(sm);

    /* Exit/Stop */
    if (exit) {
      timeshift_write_exit(ts->rd_pipe.wr);
      ts->state = TS_EXIT;
    }
  }

  pthread_mutex_unlock(&ts->state_mutex);
}