static void tsfix_input_packet(tsfix_t *tf, streaming_message_t *sm) { th_pkt_t *pkt = pkt_copy_shallow(sm->sm_data); tfstream_t *tfs = tfs_find(tf, pkt); streaming_msg_free(sm); if(tfs == NULL || dispatch_clock < tf->tf_start_time) { pkt_ref_dec(pkt); return; } if(tf->tf_tsref == PTS_UNSET && (!tf->tf_hasvideo || (SCT_ISVIDEO(tfs->tfs_type) && pkt->pkt_frametype == PKT_I_FRAME))) { tf->tf_tsref = pkt->pkt_dts & PTS_MASK; tsfixprintf("reference clock set to %"PRId64"\n", tf->tf_tsref); } if(pkt->pkt_dts == PTS_UNSET) { int pdur = pkt->pkt_duration >> pkt->pkt_field; if(tfs->tfs_last_dts_in == PTS_UNSET) { pkt_ref_dec(pkt); return; } pkt->pkt_dts = (tfs->tfs_last_dts_in + pdur) & PTS_MASK; tsfixprintf("TSFIX: %-12s DTS set to last %"PRId64" +%d == %"PRId64"\n", streaming_component_type2txt(tfs->tfs_type), tfs->tfs_last_dts_in, pdur, pkt->pkt_dts); }
static void tsfix_input_packet(tsfix_t *tf, streaming_message_t *sm) { th_pkt_t *pkt = pkt_copy_shallow(sm->sm_data); tfstream_t *tfs = tfs_find(tf, pkt); streaming_msg_free(sm); if(tfs == NULL || dispatch_clock < tf->tf_start_time) { pkt_ref_dec(pkt); return; } if(tf->tf_tsref == PTS_UNSET && (!tf->tf_hasvideo || (SCT_ISVIDEO(tfs->tfs_type) && pkt->pkt_frametype == PKT_I_FRAME))) { tf->tf_tsref = pkt->pkt_dts & PTS_MASK; tsfixprintf("reference clock set to %"PRId64"\n", tf->tf_tsref); } else { /* For teletext, the encoders might use completely different timestamps */ /* If the difference is greater than 2 seconds, use the actual dts value */ if (tfs->tfs_type == SCT_TELETEXT && tfs->tfs_local_ref == PTS_UNSET && tf->tf_tsref != PTS_UNSET && pkt->pkt_dts != PTS_UNSET) { int64_t diff = tsfix_ts_diff(tf->tf_tsref, pkt->pkt_dts); if (diff > 2 * 90000) { tfstream_t *tfs2; tvhwarn("parser", "The timediff for TELETEXT is big (%"PRId64"), using current dts", diff); tfs->tfs_local_ref = pkt->pkt_dts; /* Text subtitles extracted from teletext have same timebase */ LIST_FOREACH(tfs2, &tf->tf_streams, tfs_link) if(tfs2->tfs_type == SCT_TEXTSUB) tfs2->tfs_local_ref = pkt->pkt_dts; } else {
/* * Receive data */ static void timeshift_input ( void *opaque, streaming_message_t *sm ) { int type = sm->sm_type; timeshift_t *ts = opaque; th_pkt_t *pkt, *pkt2; if (ts->exit) return; /* Control */ if (type == SMT_SKIP) { timeshift_write_skip(ts->rd_pipe.wr, sm->sm_data); streaming_msg_free(sm); } else if (type == SMT_SPEED) { timeshift_write_speed(ts->rd_pipe.wr, sm->sm_code); streaming_msg_free(sm); } else { /* Change PTS/DTS offsets */ if (ts->packet_mode && ts->start_pts && type == SMT_PACKET) { pkt = sm->sm_data; pkt2 = pkt_copy_shallow(pkt); pkt_ref_dec(pkt); sm->sm_data = pkt2; pkt2->pkt_pts += ts->start_pts; pkt2->pkt_dts += ts->start_pts; } /* Check for exit */ else if (type == SMT_EXIT || (type == SMT_STOP && sm->sm_code != SM_CODE_SOURCE_RECONFIGURED)) ts->exit = 1; else if (type == SMT_MPEGTS) ts->packet_mode = 0; /* Send to the writer thread */ if (ts->packet_mode) { sm->sm_time = ts->last_wr_time; if ((type == SMT_PACKET) && !timeshift_packet(ts, sm)) goto _exit; } else { if (ts->ref_time == 0) { ts->ref_time = getfastmonoclock(); sm->sm_time = 0; } else { sm->sm_time = getfastmonoclock() - ts->ref_time; } } streaming_target_deliver2(&ts->wr_queue.sq_st, sm); /* Exit/Stop */ _exit: if (ts->exit) timeshift_write_exit(ts->rd_pipe.wr); } }
/* * Receive data */ static void timeshift_input ( void *opaque, streaming_message_t *sm ) { int exit = 0, type = sm->sm_type; timeshift_t *ts = opaque; th_pkt_t *pkt = sm->sm_data, *pkt2; pthread_mutex_lock(&ts->state_mutex); /* Control */ if (type == SMT_SKIP) { if (ts->state >= TS_LIVE) timeshift_write_skip(ts->rd_pipe.wr, sm->sm_data); streaming_msg_free(sm); } else if (type == SMT_SPEED) { if (ts->state >= TS_LIVE) timeshift_write_speed(ts->rd_pipe.wr, sm->sm_code); streaming_msg_free(sm); } else { /* Start */ if (type == SMT_START && ts->state == TS_INIT) ts->state = TS_LIVE; /* Change PTS/DTS offsets */ if (ts->packet_mode && ts->start_pts && type == SMT_PACKET) { pkt2 = pkt_copy_shallow(pkt); pkt_ref_dec(pkt); sm->sm_data = pkt = pkt2; pkt->pkt_pts += ts->start_pts; pkt->pkt_dts += ts->start_pts; } /* Pass-thru */ if (ts->state <= TS_LIVE) { if (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); if (ts->packet_mode) { timeshift_packet_flush(ts, ts->last_time + MAX_TIME_DELTA + 1000, ts->dobuf); if (ts->last_time) ts->start_pts = ts->last_time + 1000; } } streaming_target_deliver2(ts->output, streaming_msg_clone(sm)); } /* Check for exit */ if (type == SMT_EXIT || (type == SMT_STOP && sm->sm_code != SM_CODE_SOURCE_RECONFIGURED)) exit = 1; if (type == SMT_MPEGTS) ts->packet_mode = 0; /* Buffer to disk */ if ((ts->state > TS_LIVE) || (ts->dobuf && (ts->state == TS_LIVE))) { if (ts->packet_mode) { sm->sm_time = ts->last_time; if (type == SMT_PACKET) { timeshift_packet(ts, pkt, 1); goto msg_free; } } else { if (ts->ref_time == 0) { ts->ref_time = getmonoclock(); sm->sm_time = 0; } else { sm->sm_time = getmonoclock() - ts->ref_time; } } streaming_target_deliver2(&ts->wr_queue.sq_st, sm); } else { if (type == SMT_PACKET) { timeshift_packet(ts, pkt, 0); tvhtrace("timeshift", "ts %d pkt in - stream %d type %c pts %10"PRId64 " dts %10"PRId64" dur %10d len %6zu", 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)); } msg_free: 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); }