diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index efab8419..76391338 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -241,6 +241,9 @@ mpegts_service_stop(service_t *t) /* Stop */ if (i) i->mi_close_service(i, s); + + /* Save some memory */ + sbuf_free(&s->s_tsbuf); } /* diff --git a/src/input/mpegts/tsdemux.c b/src/input/mpegts/tsdemux.c index 7cb078d1..d9b7ee4d 100644 --- a/src/input/mpegts/tsdemux.c +++ b/src/input/mpegts/tsdemux.c @@ -297,6 +297,9 @@ ts_remux(mpegts_service_t *t, const uint8_t *src) pktbuf_t *pb; sbuf_t *sb = &t->s_tsbuf; + if (sb->sb_data == NULL) + sbuf_init_fixed(sb, TS_REMUX_BUFSIZE); + sbuf_append(sb, src, 188); if(sb->sb_ptr < TS_REMUX_BUFSIZE) @@ -312,7 +315,7 @@ ts_remux(mpegts_service_t *t, const uint8_t *src) service_set_streaming_status_flags((service_t*)t, TSS_PACKETS); - sbuf_reset(sb); + sbuf_reset(sb, TS_REMUX_BUFSIZE); } /* diff --git a/src/parsers/parsers.c b/src/parsers/parsers.c index c3f21803..8ff6e4e1 100644 --- a/src/parsers/parsers.c +++ b/src/parsers/parsers.c @@ -231,7 +231,7 @@ parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data, /* Payload unit start */ st->es_parser_state = 1; st->es_parser_ptr = 0; - sbuf_reset(&st->es_buf); + sbuf_reset(&st->es_buf, 4000); } if(st->es_parser_state == 0) @@ -351,9 +351,9 @@ parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, r = 1; } - assert(st->es_buf.sb_data != NULL); - if(r == 2) { + assert(st->es_buf.sb_data != NULL); + // Drop packet st->es_buf.sb_ptr = st->es_startcode_offset; @@ -367,12 +367,13 @@ parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, if(r == 1) { /* Reset packet parser upon length error or if parser tells us so */ - sbuf_reset(&st->es_buf); + sbuf_reset_and_alloc(&st->es_buf, 256); st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 24; st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 16; st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc >> 8; st->es_buf.sb_data[st->es_buf.sb_ptr++] = sc; } + assert(st->es_buf.sb_data != NULL); st->es_startcode = sc; st->es_startcode_offset = st->es_buf.sb_ptr - 4; } @@ -1118,17 +1119,11 @@ parse_mpeg2video(service_t *t, elementary_stream_t *st, size_t len, pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data, st->es_buf.sb_ptr - 4); pkt->pkt_duration = st->es_frame_duration; + sbuf_steal_data(&st->es_buf); parser_deliver(t, st, pkt, st->es_buf.sb_err); st->es_curpkt = NULL; - st->es_buf.sb_data = malloc(st->es_buf.sb_size); - if(st->es_buf.sb_data == NULL) { - fprintf(stderr, "Unable to allocate %d bytes\n", - st->es_buf.sb_size); - abort(); - } - return 1; } break; @@ -1248,10 +1243,10 @@ parse_h264(service_t *t, elementary_stream_t *st, size_t len, pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data, st->es_buf.sb_ptr - 4); + sbuf_steal_data(&st->es_buf); parser_deliver(t, st, pkt, st->es_buf.sb_err); st->es_curpkt = NULL; - st->es_buf.sb_data = malloc(st->es_buf.sb_size); st->es_curdts = PTS_UNSET; st->es_curpts = PTS_UNSET; @@ -1276,7 +1271,7 @@ parse_subtitles(service_t *t, elementary_stream_t *st, const uint8_t *data, if(start) { /* Payload unit start */ st->es_parser_state = 1; - sbuf_reset(&st->es_buf); + sbuf_reset(&st->es_buf, 4000); } if(st->es_parser_state == 0) @@ -1339,7 +1334,7 @@ parse_teletext(service_t *t, elementary_stream_t *st, const uint8_t *data, if(start) { st->es_parser_state = 1; st->es_parser_ptr = 0; - sbuf_reset(&st->es_buf); + sbuf_reset(&st->es_buf, 4000); } if(st->es_parser_state == 0) diff --git a/src/tvheadend.h b/src/tvheadend.h index 34b5cf13..ace8a63e 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -583,13 +583,32 @@ static inline int64_t ts_rescale_i(int64_t ts, int tb) void sbuf_init(sbuf_t *sb); +void sbuf_init_fixed(sbuf_t *sb, int len); + void sbuf_free(sbuf_t *sb); -void sbuf_reset(sbuf_t *sb); +void sbuf_reset(sbuf_t *sb, int max_len); -void sbuf_err(sbuf_t *sb); +void sbuf_reset_and_alloc(sbuf_t *sb, int len); -void sbuf_alloc(sbuf_t *sb, int len); +static inline void sbuf_steal_data(sbuf_t *sb) +{ + sb->sb_data = NULL; + sb->sb_ptr = sb->sb_size = 0; +} + +static inline void sbuf_err(sbuf_t *sb) +{ + sb->sb_err = 1; +} + +void sbuf_alloc_(sbuf_t *sb, int len); + +static inline void sbuf_alloc(sbuf_t *sb, int len) +{ + if (sb->sb_ptr + len >= sb->sb_size) + sbuf_alloc_(sb, len); +} void sbuf_append(sbuf_t *sb, const void *data, int len); diff --git a/src/utils.c b/src/utils.c index 57bcbe2b..69f51c28 100644 --- a/src/utils.c +++ b/src/utils.c @@ -247,6 +247,12 @@ put_utf8(char *out, int c) return 6; } +static void +sbuf_alloc_fail(int len) +{ + fprintf(stderr, "Unable to allocate %d bytes\n", len); + abort(); +} void sbuf_init(sbuf_t *sb) @@ -254,62 +260,77 @@ sbuf_init(sbuf_t *sb) memset(sb, 0, sizeof(sbuf_t)); } +void +sbuf_init_fixed(sbuf_t *sb, int len) +{ + memset(sb, 0, sizeof(sbuf_t)); + sb->sb_data = malloc(len); + if (sb->sb_data == NULL) + sbuf_alloc_fail(len); + sb->sb_size = len; +} void sbuf_free(sbuf_t *sb) { - if(sb->sb_data) - free(sb->sb_data); + free(sb->sb_data); sb->sb_size = sb->sb_ptr = sb->sb_err = 0; sb->sb_data = NULL; } void -sbuf_reset(sbuf_t *sb) +sbuf_reset(sbuf_t *sb, int max_len) { - sb->sb_ptr = 0; - sb->sb_err = 0; + sb->sb_ptr = sb->sb_err = 0; + if (sb->sb_size > max_len) { + void *n = realloc(sb->sb_data, max_len); + if (n) { + sb->sb_data = n; + sb->sb_size = max_len; + } + } } void -sbuf_err(sbuf_t *sb) +sbuf_reset_and_alloc(sbuf_t *sb, int len) { - sb->sb_err = 1; + if (sb->sb_data) { + if (len != sb->sb_size) { + void *n = realloc(sb->sb_data, len); + if (n) { + sb->sb_data = n; + sb->sb_size = len; + } + } + } else { + sb->sb_data = malloc(len); + sb->sb_size = len; + } + if (sb->sb_data == NULL) + sbuf_alloc_fail(len); + sb->sb_ptr = sb->sb_err = 0; } void -sbuf_alloc(sbuf_t *sb, int len) +sbuf_alloc_(sbuf_t *sb, int len) { if(sb->sb_data == NULL) { sb->sb_size = len * 4 > 4000 ? len * 4 : 4000; sb->sb_data = malloc(sb->sb_size); return; - } - - if(sb->sb_ptr + len >= sb->sb_size) { + } else { sb->sb_size += len * 4; sb->sb_data = realloc(sb->sb_data, sb->sb_size); } -} -static void -sbuf_alloc1(sbuf_t *sb, int len) -{ - if(sb->sb_data == NULL) { - sb->sb_size = len * 4 > 4000 ? len * 4 : 4000; - sb->sb_data = malloc(sb->sb_size); - return; - } - - sb->sb_size += len * 4; - sb->sb_data = realloc(sb->sb_data, sb->sb_size); + if(sb->sb_data == NULL) + sbuf_alloc_fail(sb->sb_size); } void sbuf_append(sbuf_t *sb, const void *data, int len) { - if(sb->sb_ptr + len >= sb->sb_size) - sbuf_alloc1(sb, len); + sbuf_alloc(sb, len); memcpy(sb->sb_data + sb->sb_ptr, data, len); sb->sb_ptr += len; }