This allows the code to modify packets (which are non-mutable due to reference counting)
by copying them without having to also copy the packet payload.
if(ssc->ssc_lang[0])
ebml_append_string(t, 0x22b59c, ssc->ssc_lang);
- if(ssc->ssc_global_header_len) {
+ if(ssc->ssc_gh) {
switch(ssc->ssc_type) {
case SCT_H264:
case SCT_MPEG2VIDEO:
case SCT_AAC:
- ebml_append_bin(t, 0x63a2, ssc->ssc_global_header,
- ssc->ssc_global_header_len);
+ ebml_append_bin(t, 0x63a2,
+ pktbuf_ptr(ssc->ssc_gh),
+ pktbuf_len(ssc->ssc_gh));
break;
}
}
}
- data = pkt->pkt_payload;
- len = pkt->pkt_payloadlen;
+ data = pktbuf_ptr(pkt->pkt_payload);
+ len = pktbuf_len(pkt->pkt_payload);
if(t->type == SCT_AAC) {
// Skip ADTS header
if(t != NULL) {
if(t->merge)
- pkt = pkt_merge_global(pkt);
+ pkt = pkt_merge_header(pkt);
mk_write_frame_i(mkm, t, pkt);
}
int hm_payloadsize; /* For maintaining stats about streaming
buffer depth */
- th_pkt_t *hm_pkt; /* For keeping reference to packet.
+ pktbuf_t *hm_pb; /* For keeping reference to packet payload.
hm_msg can contain messages that points
to packet payload so to avoid copy we
keep a reference here */
htsp_msg_destroy(htsp_msg_t *hm)
{
htsmsg_destroy(hm->hm_msg);
- if(hm->hm_pkt != NULL)
- pkt_ref_dec(hm->hm_pkt);
+ if(hm->hm_pb != NULL)
+ pktbuf_ref_dec(hm->hm_pb);
free(hm);
}
*
*/
static void
-htsp_send(htsp_connection_t *htsp, htsmsg_t *m, th_pkt_t *pkt,
+htsp_send(htsp_connection_t *htsp, htsmsg_t *m, pktbuf_t *pb,
htsp_msg_q_t *hmq, int payloadsize)
{
htsp_msg_t *hm = malloc(sizeof(htsp_msg_t));
hm->hm_msg = m;
- hm->hm_pkt = pkt;
+ hm->hm_pb = pb;
+ if(pb != NULL)
+ pktbuf_ref_inc(pb);
hm->hm_payloadsize = payloadsize;
pthread_mutex_lock(&htsp->htsp_out_mutex);
uint32_t dur = ts_rescale(pkt->pkt_duration, 1000000);
htsmsg_add_u32(m, "duration", dur);
- pkt = pkt_merge_global(pkt);
+ pkt = pkt_merge_header(pkt);
/**
* Since we will serialize directly we use 'binptr' which is a binary
* object that just points to data, thus avoiding a copy.
*/
- htsmsg_add_binptr(m, "payload", pkt->pkt_payload, pkt->pkt_payloadlen);
- htsp_send(htsp, m, pkt, &hs->hs_q, pkt->pkt_payloadlen);
+ htsmsg_add_binptr(m, "payload", pktbuf_ptr(pkt->pkt_payload),
+ pktbuf_len(pkt->pkt_payload));
+ htsp_send(htsp, m, pkt->pkt_payload, &hs->hs_q, pktbuf_len(pkt->pkt_payload));
if(hs->hs_last_report != dispatch_clock) {
/* Send a queue status report every second */
htsp_send_message(hs->hs_htsp, m, &hs->hs_htsp->htsp_hmq_qstatus);
}
+ pkt_ref_dec(pkt);
}
static void
pkt_destroy(th_pkt_t *pkt)
{
- free(pkt->pkt_payload);
- free(pkt->pkt_globaldata);
+ if(pkt->pkt_payload != NULL)
+ pktbuf_ref_dec(pkt->pkt_payload);
+
+ if(pkt->pkt_header != NULL)
+ pktbuf_ref_dec(pkt->pkt_header);
free(pkt);
}
th_pkt_t *pkt;
pkt = calloc(1, sizeof(th_pkt_t));
- pkt->pkt_payloadlen = datalen;
- if(datalen > 0) {
- pkt->pkt_payload = malloc(datalen);
- if(data != NULL)
- memcpy(pkt->pkt_payload, data, datalen);
- }
-
+ if(datalen)
+ pkt->pkt_payload = pktbuf_alloc(data, datalen);
pkt->pkt_dts = dts;
pkt->pkt_pts = pts;
pkt->pkt_refcount = 1;
*
*/
th_pkt_t *
-pkt_merge_global(th_pkt_t *pkt)
+pkt_merge_header(th_pkt_t *pkt)
{
th_pkt_t *n;
+ size_t s;
- if(pkt->pkt_globaldata == NULL)
+ if(pkt->pkt_header == NULL)
return pkt;
n = malloc(sizeof(th_pkt_t));
*n = *pkt;
n->pkt_refcount = 1;
- n->pkt_globaldata = NULL;
- n->pkt_globaldata_len = 0;
-
- n->pkt_payloadlen = pkt->pkt_globaldata_len + pkt->pkt_payloadlen;
+ n->pkt_header = NULL;
- n->pkt_payload = malloc(n->pkt_payloadlen);
- memcpy(n->pkt_payload, pkt->pkt_globaldata, pkt->pkt_globaldata_len);
- memcpy(n->pkt_payload + pkt->pkt_globaldata_len, pkt->pkt_payload,
- pkt->pkt_payloadlen);
+ s = pktbuf_len(pkt->pkt_payload) + pktbuf_len(pkt->pkt_header);
+ n->pkt_payload = pktbuf_alloc(NULL, s);
+
+ memcpy(pktbuf_ptr(n->pkt_payload),
+ pktbuf_ptr(pkt->pkt_header),
+ pktbuf_len(pkt->pkt_header));
+
+ memcpy(pktbuf_ptr(n->pkt_payload) + pktbuf_len(pkt->pkt_header),
+ pktbuf_ptr(pkt->pkt_payload),
+ pktbuf_len(pkt->pkt_payload));
pkt_ref_dec(pkt);
-
return n;
}
*
*/
th_pkt_t *
-pkt_copy(th_pkt_t *pkt)
+pkt_copy_shallow(th_pkt_t *pkt)
{
th_pkt_t *n = malloc(sizeof(th_pkt_t));
*n = *pkt;
n->pkt_refcount = 1;
- if(pkt->pkt_globaldata_len) {
- n->pkt_globaldata = malloc(pkt->pkt_globaldata_len);
- memcpy(n->pkt_globaldata, pkt->pkt_globaldata, pkt->pkt_globaldata_len);
- }
+ if(n->pkt_header)
+ pktbuf_ref_inc(n->pkt_header);
- if(pkt->pkt_payloadlen) {
- n->pkt_payload = malloc(pkt->pkt_payloadlen);
- memcpy(n->pkt_payload, pkt->pkt_payload, pkt->pkt_payloadlen);
- }
+ if(n->pkt_payload)
+ pktbuf_ref_inc(n->pkt_payload);
return n;
}
pr->pr_pkt = pkt;
return pr;
}
+
+
+
+void
+pktbuf_ref_dec(pktbuf_t *pb)
+{
+ if((atomic_add(&pb->pb_refcount, -1)) == 1) {
+ free(pb->pb_data);
+ free(pb);
+ }
+}
+
+void
+pktbuf_ref_inc(pktbuf_t *pb)
+{
+ atomic_add(&pb->pb_refcount, 1);
+}
+
+pktbuf_t *
+pktbuf_alloc(const void *data, size_t size)
+{
+ pktbuf_t *pb = malloc(sizeof(pktbuf_t));
+ pb->pb_refcount = 1;
+ pb->pb_size = size;
+
+ if(size > 0) {
+ pb->pb_data = malloc(size);
+ if(data != NULL)
+ memcpy(pb->pb_data, data, size);
+ }
+ return pb;
+}
+
+pktbuf_t *
+pktbuf_make(void *data, size_t size)
+{
+ pktbuf_t *pb = malloc(sizeof(pktbuf_t));
+ pb->pb_refcount = 1;
+ pb->pb_size = size;
+ pb->pb_data = data;
+ return pb;
+}
#define PACKET_H_
+typedef struct pktbuf {
+ int pb_refcount;
+ uint8_t *pb_data;
+ size_t pb_size;
+} pktbuf_t;
+
+
+
/**
* Packets
*/
uint8_t pkt_channels;
uint8_t pkt_sri;
- uint8_t *pkt_payload;
- int pkt_payloadlen;
-
- uint8_t *pkt_globaldata;
- int pkt_globaldata_len;
+ pktbuf_t *pkt_payload;
+ pktbuf_t *pkt_header;
} th_pkt_t;
th_pkt_t *pkt_alloc(const void *data, size_t datalen, int64_t pts, int64_t dts);
-th_pkt_t *pkt_merge_global(th_pkt_t *pkt);
+th_pkt_t *pkt_merge_header(th_pkt_t *pkt);
-th_pkt_t *pkt_copy(th_pkt_t *pkt);
+th_pkt_t *pkt_copy_shallow(th_pkt_t *pkt);
th_pktref_t *pktref_create(th_pkt_t *pkt);
+void pktbuf_ref_dec(pktbuf_t *pb);
+
+void pktbuf_ref_inc(pktbuf_t *pb);
+
+pktbuf_t *pktbuf_alloc(const void *data, size_t size);
+
+pktbuf_t *pktbuf_make(void *data, size_t size);
+
+#define pktbuf_len(pb) ((pb)->pb_size)
+#define pktbuf_ptr(pb) ((pb)->pb_data)
+
#endif /* PACKET_H_ */
if(st->st_curdts == PTS_UNSET)
return NULL;
- th_pkt_t *pkt = pkt_alloc(NULL, 0, st->st_curdts, st->st_curdts);
+ th_pkt_t *pkt = pkt_alloc(NULL, slot_len + 7, st->st_curdts, st->st_curdts);
pkt->pkt_commercial = t->tht_tt_commercial_advice;
- pkt->pkt_payloadlen = slot_len + 7;
- pkt->pkt_payload = malloc(pkt->pkt_payloadlen);
pkt->pkt_duration = st->st_frame_duration;
pkt->pkt_sri = latm->sample_rate_index;
pkt->pkt_channels = latm->channel_config;
/* 7 bytes of ADTS header */
- init_bits(&out, pkt->pkt_payload, 56);
+ init_bits(&out, pktbuf_ptr(pkt->pkt_payload), 56);
put_bits(&out, 0xfff, 12); // Sync marker
put_bits(&out, 0, 1); // ID 0 = MPEG 4
assert(remaining_bits(&out) == 0);
/* AAC RDB */
- buf = pkt->pkt_payload + 7;
+ buf = pktbuf_ptr(pkt->pkt_payload) + 7;
for(i = 0; i < slot_len; i++)
*buf++ = read_bits(&bs, 8);
}
if(st->st_global_data) {
- pkt->pkt_globaldata = st->st_global_data;
- pkt->pkt_globaldata_len = st->st_global_data_len;
-
+ pkt->pkt_header = pktbuf_make(st->st_global_data,
+ st->st_global_data_len);
st->st_global_data = NULL;
st->st_global_data_len = 0;
}
- pkt->pkt_payload = st->st_buffer;
- pkt->pkt_payloadlen = st->st_buffer_ptr - 4;
+ pkt->pkt_payload = pktbuf_make(st->st_buffer, st->st_buffer_ptr - 4);
pkt->pkt_duration = st->st_frame_duration;
parser_deliver(t, st, pkt);
if(pkt != NULL) {
if(st->st_global_data) {
- pkt->pkt_globaldata = st->st_global_data;
- pkt->pkt_globaldata_len = st->st_global_data_len;
+ pkt->pkt_header = pktbuf_make(st->st_global_data,
+ st->st_global_data_len);
st->st_global_data = NULL;
st->st_global_data_len = 0;
}
- pkt->pkt_payload = st->st_buffer;
- pkt->pkt_payloadlen = st->st_buffer_ptr - 4;
+ pkt->pkt_payload = pktbuf_make(st->st_buffer, st->st_buffer_ptr - 4);
parser_deliver(t, st, pkt);
st->st_curpkt = NULL;
pkt->pkt_payloadlen);
#endif
- avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
+ // avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
/**
* Input is ok
#include "tvhead.h"
#include "streaming.h"
#include "globalheaders.h"
-#include "avc.h"
typedef struct globalheaders {
streaming_target_t gh_input;
if(ssc->ssc_frameduration == 0 && pkt->pkt_duration != 0)
ssc->ssc_frameduration = pkt->pkt_duration;
- if(ssc->ssc_global_header != NULL)
+ if(ssc->ssc_gh != NULL)
return;
switch(ssc->ssc_type) {
case SCT_AAC:
- d = ssc->ssc_global_header = malloc(2);
- ssc->ssc_global_header_len = 2;
+ ssc->ssc_gh = pktbuf_alloc(NULL, 2);
+ d = pktbuf_ptr(ssc->ssc_gh);
const int profile = 2;
d[0] = (profile << 3) | ((pkt->pkt_sri & 0xe) >> 1);
case SCT_H264:
case SCT_MPEG2VIDEO:
- if(pkt->pkt_globaldata != NULL) {
- ssc->ssc_global_header = malloc(pkt->pkt_globaldata_len +
- FF_INPUT_BUFFER_PADDING_SIZE);
-
- memcpy(ssc->ssc_global_header, pkt->pkt_globaldata,
- pkt->pkt_globaldata_len);
- ssc->ssc_global_header_len = pkt->pkt_globaldata_len;
+ if(pkt->pkt_header != NULL) {
+ ssc->ssc_gh = pkt->pkt_header;
+ pktbuf_ref_inc(ssc->ssc_gh);
}
break;
ssc->ssc_frameduration == 0)
return 0;
- if(ssc->ssc_global_header == NULL &&
+ if(ssc->ssc_gh == NULL &&
(ssc->ssc_type == SCT_H264 ||
ssc->ssc_type == SCT_MPEG2VIDEO ||
ssc->ssc_type == SCT_AAC))
pkt->pkt_dts,
pkt->pkt_pts,
pkt->pkt_duration,
- pkt->pkt_payloadlen);
+ pktbuf_len(pkt->pkt_payload));
streaming_message_t *sm = streaming_msg_create_pkt(pkt);
streaming_target_deliver2(tf->tf_output, sm);
static void
tsfix_input_packet(tsfix_t *tf, streaming_message_t *sm)
{
- th_pkt_t *pkt = pkt_copy(sm->sm_data);
+ th_pkt_t *pkt = pkt_copy_shallow(sm->sm_data);
tfstream_t *tfs = tfs_find(tf, pkt);
streaming_msg_free(sm);
{
rtsp_stream_t *rs;
- pkt = pkt_merge_global(pkt);
+ pkt = pkt_merge_header(pkt);
LIST_FOREACH(rs, &rtsp->rtsp_streams, rs_link)
if(rs->rs_index == pkt->pkt_componentindex)
switch(rs->rs_type) {
case SCT_MPEG2VIDEO:
- rtp_send_mpv(rs->rs_sender, rs, &rs->rs_rtp, pkt->pkt_payload,
- pkt->pkt_payloadlen, pkt->pkt_pts);
+ rtp_send_mpv(rs->rs_sender, rs, &rs->rs_rtp,
+ pktbuf_ptr(pkt->pkt_payload),
+ pktbuf_len(pkt->pkt_payload),
+ pkt->pkt_pts);
break;
case SCT_MPEG2AUDIO:
- rtp_send_mpa(rs->rs_sender, rs, &rs->rs_rtp, pkt->pkt_payload,
- pkt->pkt_payloadlen, pkt->pkt_pts);
+ rtp_send_mpa(rs->rs_sender, rs, &rs->rs_rtp,
+ pktbuf_ptr(pkt->pkt_payload),
+ pktbuf_len(pkt->pkt_payload),
+ pkt->pkt_pts);
break;
}
}
transport_source_info_free(&ss->ss_si);
for(i = 0; i < ss->ss_num_components; i++)
- free(ss->ss_components[i].ssc_global_header);
-
+ if(ss->ss_components[i].ssc_gh)
+ pktbuf_ref_dec(ss->ss_components[i].ssc_gh);
free(ss);
}
for(i = 0; i < dst->ss_num_components; i++) {
streaming_start_component_t *ssc = &dst->ss_components[i];
- if(ssc->ssc_global_header != NULL)
- ssc->ssc_global_header = memcpy(malloc(ssc->ssc_global_header_len),
- ssc->ssc_global_header,
- ssc->ssc_global_header_len);
+ if(ssc->ssc_gh != NULL)
+ pktbuf_ref_inc(ssc->ssc_gh);
}
dst->ss_refcount = 1;
int16_t ssc_width;
int16_t ssc_height;
- uint8_t *ssc_global_header;
- int ssc_global_header_len;
+ pktbuf_t *ssc_gh;
int ssc_frameduration;