/** * Allocate a new packet and give it a refcount of one (which caller is * suppoed to take care of) */ th_pkt_t * pkt_alloc(streaming_component_type_t type, const uint8_t *data, size_t datalen, int64_t pts, int64_t dts, int64_t pcr) { th_pkt_t *pkt; pktbuf_t *payload; if (datalen > 0) { payload = pktbuf_alloc(data, datalen); if (payload == NULL) return NULL; } else { payload = NULL; } pkt = calloc(1, sizeof(th_pkt_t)); if (pkt) { pkt->pkt_type = type; pkt->pkt_payload = payload; pkt->pkt_dts = dts; pkt->pkt_pts = pts; pkt->pkt_pcr = pcr; pkt->pkt_refcount = 1; memoryinfo_alloc(&pkt_memoryinfo, sizeof(*pkt)); } else { if (payload) pktbuf_ref_dec(payload); } return pkt; }
pktbuf_t * pktbuf_alloc(const uint8_t *data, size_t size) { pktbuf_t *pb; uint8_t *buffer; buffer = size > 0 ? malloc(size) : NULL; if (buffer) {\ if (data != NULL) memcpy(buffer, data, size); } else if (size > 0) { return NULL; } pb = malloc(sizeof(pktbuf_t)); if (pb == NULL) { free(buffer); return NULL; } pb->pb_refcount = 1; pb->pb_data = buffer; pb->pb_size = size; pb->pb_err = 0; memoryinfo_alloc(&pktbuf_memoryinfo, sizeof(*pb) + size); return pb; }
/* * Stream start handling */ static void _handle_sstart ( timeshift_t *ts, timeshift_file_t *tsf, streaming_message_t *sm ) { timeshift_index_data_t *ti = calloc(1, sizeof(timeshift_index_data_t)); memoryinfo_alloc(×hift_memoryinfo, sizeof(*ti)); ti->pos = tsf->size; ti->data = sm; TAILQ_INSERT_TAIL(&tsf->sstart, ti, link); }
th_pktref_t * pktref_create(th_pkt_t *pkt) { th_pktref_t *pr = malloc(sizeof(th_pktref_t)); if (pr) { pr->pr_pkt = pkt; memoryinfo_alloc(&pktref_memoryinfo, sizeof(*pr)); } return pr; }
/** * Reference count is transfered to queue */ void pktref_enqueue(struct th_pktref_queue *q, th_pkt_t *pkt) { th_pktref_t *pr = malloc(sizeof(th_pktref_t)); if (pr) { pr->pr_pkt = pkt; TAILQ_INSERT_TAIL(q, pr, pr_link); memoryinfo_alloc(&pktref_memoryinfo, sizeof(*pr)); } }
tasklet_t * tasklet_arm_alloc(tsk_callback_t *callback, void *opaque) { tasklet_t *tsk = calloc(1, sizeof(*tsk)); if (tsk) { memoryinfo_alloc(&tasklet_memoryinfo, sizeof(*tsk)); tsk->tsk_free = free; tasklet_arm(tsk, callback, opaque); } return tsk; }
/** * Reference count is transfered to queue */ void pktref_enqueue_sorted(struct th_pktref_queue *q, th_pkt_t *pkt, int (*cmp)(const void *, const void *)) { th_pktref_t *pr = malloc(sizeof(th_pktref_t)); if (pr) { pr->pr_pkt = pkt; TAILQ_INSERT_SORTED(q, pr, pr_link, cmp); memoryinfo_alloc(&pktref_memoryinfo, sizeof(*pr)); } }
streaming_message_t * streaming_msg_create(streaming_message_type_t type) { streaming_message_t *sm = malloc(sizeof(streaming_message_t)); memoryinfo_alloc(&streaming_msg_memoryinfo, sizeof(*sm)); sm->sm_type = type; #if ENABLE_TIMESHIFT sm->sm_time = 0; #endif return sm; }
pktbuf_t * pktbuf_make(void *data, size_t size) { pktbuf_t *pb = malloc(sizeof(pktbuf_t)); if (pb) { pb->pb_refcount = 1; pb->pb_size = size; pb->pb_data = data; memoryinfo_alloc(&pktbuf_memoryinfo, sizeof(*pb) + pb->pb_size); } return pb; }
/** * Create timeshift buffer * * max_period of buffer in seconds (0 = unlimited) * max_size of buffer in bytes (0 = unlimited) */ streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_time) { timeshift_t *ts = calloc(1, sizeof(timeshift_t)); memoryinfo_alloc(×hift_memoryinfo, sizeof(timeshift_t)); /* Must hold global lock */ lock_assert(&global_lock); /* Setup structure */ TAILQ_INIT(&ts->files); ts->output = out; ts->path = NULL; ts->max_time = max_time; ts->state = TS_LIVE; ts->exit = 0; ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; ts->ondemand = timeshift_conf.ondemand; ts->dobuf = ts->ondemand ? 0 : 1; ts->packet_mode= 1; ts->last_wr_time = 0; ts->buf_time = 0; ts->start_pts = 0; ts->ref_time = 0; ts->seek.file = NULL; ts->seek.frame = NULL; ts->ram_segments = 0; ts->file_segments = 0; pthread_mutex_init(&ts->state_mutex, NULL); /* Initialise output */ tvh_pipe(O_NONBLOCK, &ts->rd_pipe); /* Initialise input */ streaming_queue_init(&ts->wr_queue, 0, 0); streaming_target_init(&ts->input, ×hift_input_ops, ts, 0); tvhthread_create(&ts->wr_thread, NULL, timeshift_writer, ts, "tshift-wr"); tvhthread_create(&ts->rd_thread, NULL, timeshift_reader, ts, "tshift-rd"); /* Update index */ timeshift_index++; return &ts->input; }
th_pkt_t * pkt_copy_nodata(th_pkt_t *pkt) { th_pkt_t *n = malloc(sizeof(th_pkt_t)); if (n) { blacklisted_memcpy(n, pkt, sizeof(*pkt)); n->pkt_refcount = 1; n->pkt_meta = n->pkt_payload = NULL; memoryinfo_alloc(&pkt_memoryinfo, sizeof(*pkt)); } return n; }
th_pkt_t * pkt_copy_shallow(th_pkt_t *pkt) { th_pkt_t *n = malloc(sizeof(th_pkt_t)); if (n) { blacklisted_memcpy(n, pkt, sizeof(*pkt)); n->pkt_refcount = 1; pktbuf_ref_inc(n->pkt_meta); pktbuf_ref_inc(n->pkt_payload); memoryinfo_alloc(&pkt_memoryinfo, sizeof(*pkt)); } return n; }
static inline ssize_t _process_msg0 ( timeshift_t *ts, timeshift_file_t *tsf, streaming_message_t *sm ) { ssize_t err; if (sm->sm_type == SMT_START) { err = 0; _handle_sstart(ts, tsf, streaming_msg_clone(sm)); } else if (sm->sm_type == SMT_SIGNAL_STATUS) err = timeshift_write_sigstat(tsf, sm->sm_time, sm->sm_data); else if (sm->sm_type == SMT_PACKET) { err = timeshift_write_packet(tsf, sm->sm_time, sm->sm_data); if (err > 0) { th_pkt_t *pkt = sm->sm_data; /* Index video iframes */ if (pkt->pkt_componentindex == ts->vididx && pkt->pkt_frametype == PKT_I_FRAME) { timeshift_index_iframe_t *ti = calloc(1, sizeof(timeshift_index_iframe_t)); memoryinfo_alloc(×hift_memoryinfo, sizeof(*ti)); ti->pos = tsf->size; ti->time = sm->sm_time; TAILQ_INSERT_TAIL(&tsf->iframes, ti, link); } } } else if (sm->sm_type == SMT_MPEGTS) { err = timeshift_write_mpegts(tsf, sm->sm_time, sm->sm_data); } else err = 0; /* OK */ if (err > 0) { tsf->last = sm->sm_time; tsf->size += err; atomic_add_u64(×hift_total_size, err); if (tsf->ram) atomic_add_u64(×hift_total_ram_size, err); } return err; }
streaming_message_t * streaming_msg_clone(streaming_message_t *src) { streaming_message_t *dst = malloc(sizeof(streaming_message_t)); streaming_start_t *ss; memoryinfo_alloc(&streaming_msg_memoryinfo, sizeof(*dst)); dst->sm_type = src->sm_type; #if ENABLE_TIMESHIFT dst->sm_time = src->sm_time; #endif switch(src->sm_type) { case SMT_PACKET: pkt_ref_inc(src->sm_data); dst->sm_data = src->sm_data; break; case SMT_START: ss = dst->sm_data = src->sm_data; streaming_start_ref(ss); break; case SMT_SKIP: dst->sm_data = malloc(sizeof(streaming_skip_t)); memcpy(dst->sm_data, src->sm_data, sizeof(streaming_skip_t)); break; case SMT_SIGNAL_STATUS: dst->sm_data = malloc(sizeof(signal_status_t)); memcpy(dst->sm_data, src->sm_data, sizeof(signal_status_t)); break; case SMT_DESCRAMBLE_INFO: dst->sm_data = malloc(sizeof(descramble_info_t)); memcpy(dst->sm_data, src->sm_data, sizeof(descramble_info_t)); break; case SMT_TIMESHIFT_STATUS: dst->sm_data = malloc(sizeof(timeshift_status_t)); memcpy(dst->sm_data, src->sm_data, sizeof(timeshift_status_t)); break; case SMT_GRACE: case SMT_SPEED: case SMT_STOP: case SMT_SERVICE_STATUS: case SMT_NOSTART: case SMT_NOSTART_WARN: dst->sm_code = src->sm_code; break; case SMT_EXIT: break; case SMT_MPEGTS: pktbuf_ref_inc(src->sm_data); dst->sm_data = src->sm_data; break; default: abort(); } return dst; }