From 6f85b14767f3d87e5aebf5711cc8149a9dfe3a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 3 Jul 2010 16:18:50 +0000 Subject: [PATCH] Refactor parsing buffer handling + better constification --- src/bitstream.c | 21 ++++-- src/bitstream.h | 7 +- src/dvr/mkmux.c | 1 + src/parser_h264.c | 18 ++--- src/parser_h264.h | 2 +- src/parser_latm.c | 8 +-- src/parser_latm.h | 2 +- src/parsers.c | 165 +++++++++++++++++++++------------------------- src/transports.c | 20 ++---- src/tvhead.h | 37 +++++++---- src/utils.c | 53 +++++++++++++++ src/v4l.c | 22 +++---- 12 files changed, 206 insertions(+), 150 deletions(-) diff --git a/src/bitstream.c b/src/bitstream.c index be5ce929..b8808199 100644 --- a/src/bitstream.c +++ b/src/bitstream.c @@ -22,9 +22,20 @@ void -init_bits(bitstream_t *bs, uint8_t *data, int bits) +init_rbits(bitstream_t *bs, const uint8_t *data, int bits) { - bs->data = data; + bs->wdata = NULL; + bs->rdata = data; + bs->offset = 0; + bs->len = bits; +} + + +void +init_wbits(bitstream_t *bs, uint8_t *data, int bits) +{ + bs->wdata = data; + bs->rdata = NULL; bs->offset = 0; bs->len = bits; } @@ -46,7 +57,7 @@ read_bits(bitstream_t *bs, int num) num--; - if(bs->data[bs->offset / 8] & (1 << (7 - (bs->offset & 7)))) + if(bs->rdata[bs->offset / 8] & (1 << (7 - (bs->offset & 7)))) r |= 1 << num; bs->offset++; @@ -103,9 +114,9 @@ put_bits(bitstream_t *bs, int val, int num) num--; if(val & (1 << num)) - bs->data[bs->offset / 8] |= 1 << (7 - (bs->offset & 7)); + bs->wdata[bs->offset / 8] |= 1 << (7 - (bs->offset & 7)); else - bs->data[bs->offset / 8] &= ~(1 << (7 - (bs->offset & 7))); + bs->wdata[bs->offset / 8] &= ~(1 << (7 - (bs->offset & 7))); bs->offset++; } diff --git a/src/bitstream.h b/src/bitstream.h index 40dd420d..5aa468bf 100644 --- a/src/bitstream.h +++ b/src/bitstream.h @@ -20,14 +20,17 @@ #define BITSTREAM_H_ typedef struct bitstream { - uint8_t *data; + const uint8_t *rdata; + uint8_t *wdata; int offset; int len; } bitstream_t; void skip_bits(bitstream_t *bs, int num); -void init_bits(bitstream_t *bs, uint8_t *data, int bits); +void init_rbits(bitstream_t *bs, const uint8_t *data, int bits); + +void init_wbits(bitstream_t *bs, uint8_t *data, int bits); unsigned int read_bits(bitstream_t *gb, int num); diff --git a/src/dvr/mkmux.c b/src/dvr/mkmux.c index 53c3e5f8..3fa77df9 100644 --- a/src/dvr/mkmux.c +++ b/src/dvr/mkmux.c @@ -145,6 +145,7 @@ mk_build_segment_info(mk_mux_t *mkm) ebml_append_string(q, 0x4d80, "HTS Tvheadend Matroska muxer"); ebml_append_string(q, 0x5741, app); ebml_append_uint(q, 0x2ad7b1, MATROSKA_TIMESCALE); + printf("Writing total duration %f\n", (float)mkm->totduration); if(mkm->totduration) ebml_append_float(q, 0x4489, (float)mkm->totduration); else diff --git a/src/parser_h264.c b/src/parser_h264.c index d986b512..55c926c4 100644 --- a/src/parser_h264.c +++ b/src/parser_h264.c @@ -36,29 +36,29 @@ /** * H.264 parser, nal escaper */ -int -h264_nal_deescape(bitstream_t *bs, uint8_t *data, int size) +void * +h264_nal_deescape(bitstream_t *bs, const uint8_t *data, int size) { int rbsp_size, i; - - bs->data = malloc(size); + uint8_t *d = malloc(size); + bs->rdata = d; /* Escape 0x000003 into 0x0000 */ rbsp_size = 0; for(i = 1; i < size; i++) { if(i + 2 < size && data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 3) { - bs->data[rbsp_size++] = 0; - bs->data[rbsp_size++] = 0; + d[rbsp_size++] = 0; + d[rbsp_size++] = 0; i += 2; } else { - bs->data[rbsp_size++] = data[i]; + d[rbsp_size++] = data[i]; } } bs->offset = 0; bs->len = rbsp_size * 8; - return 0; + return d; } @@ -353,7 +353,7 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype, st->st_vbv_delay = -1; - if(p->sps[sps_id].width && p->sps[sps_id].height && !st->st_buffer_errors) + if(p->sps[sps_id].width && p->sps[sps_id].height && !st->st_buf.sb_err) parser_set_stream_vsize(st, p->sps[sps_id].width, p->sps[sps_id].height); return 0; } diff --git a/src/parser_h264.h b/src/parser_h264.h index cdbfa35f..ac63fbdb 100644 --- a/src/parser_h264.h +++ b/src/parser_h264.h @@ -21,7 +21,7 @@ #include "bitstream.h" -int h264_nal_deescape(bitstream_t *bs, uint8_t *data, int size); +void *h264_nal_deescape(bitstream_t *bs, const uint8_t *data, int size); int h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs); diff --git a/src/parser_latm.c b/src/parser_latm.c index d04cb682..08656a64 100644 --- a/src/parser_latm.c +++ b/src/parser_latm.c @@ -159,15 +159,15 @@ read_stream_mux_config(th_stream_t *st, latm_private_t *latm, bitstream_t *bs) * Parse AAC LATM */ th_pkt_t * -parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, uint8_t *data, - int len) +parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, + const uint8_t *data, int len) { latm_private_t *latm; bitstream_t bs, out; int slot_len, tmp, i; uint8_t *buf; - init_bits(&bs, data, len * 8); + init_rbits(&bs, data, len * 8); if((latm = st->st_priv) == NULL) latm = st->st_priv = calloc(1, sizeof(latm_private_t)); @@ -202,7 +202,7 @@ parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, uint8_t *data, pkt->pkt_channels = latm->channel_config; /* 7 bytes of ADTS header */ - init_bits(&out, pktbuf_ptr(pkt->pkt_payload), 56); + init_wbits(&out, pktbuf_ptr(pkt->pkt_payload), 56); put_bits(&out, 0xfff, 12); // Sync marker put_bits(&out, 0, 1); // ID 0 = MPEG 4 diff --git a/src/parser_latm.h b/src/parser_latm.h index 04dec3ba..94816869 100644 --- a/src/parser_latm.h +++ b/src/parser_latm.h @@ -20,6 +20,6 @@ #define PARSER_LATM_H_ th_pkt_t *parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, - uint8_t *data, int len); + const uint8_t *data, int len); #endif /* PARSER_LATM_H_ */ diff --git a/src/parsers.c b/src/parsers.c index 31fc1232..6ebf9f91 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -120,11 +120,9 @@ void parse_mpeg_ts(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start, int err) { - if(start) - st->st_buffer_errors = 0; - + if(err) - st->st_buffer_errors++; + sbuf_err(&st->st_buf); switch(st->st_type) { case SCT_MPEG2VIDEO: @@ -194,7 +192,7 @@ parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len) } } - +#if 0 /** * */ @@ -266,7 +264,7 @@ buffer3_cut(th_stream_t *st, int p) memmove(st->st_buffer3, st->st_buffer3 + p, st->st_buffer3_ptr); } - +#endif /** * Parse AAC LATM @@ -281,34 +279,24 @@ parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data, if(start) { /* Payload unit start */ st->st_parser_state = 1; - st->st_buffer_ptr = 0; st->st_parser_ptr = 0; + sbuf_reset(&st->st_buf); } if(st->st_parser_state == 0) return; - if(st->st_buffer == NULL) { - st->st_buffer_size = 4000; - st->st_buffer = malloc(st->st_buffer_size); - } - - if(st->st_buffer_ptr + len >= st->st_buffer_size) { - st->st_buffer_size += len * 4; - st->st_buffer = realloc(st->st_buffer, st->st_buffer_size); - } - - memcpy(st->st_buffer + st->st_buffer_ptr, data, len); - st->st_buffer_ptr += len; + sbuf_append(&st->st_buf, data, len); if(st->st_parser_ptr == 0) { int hlen; - if(st->st_buffer_ptr < 9) + if(st->st_buf.sb_ptr < 9) return; - hlen = parse_pes_header(t, st, st->st_buffer + 6, st->st_buffer_ptr - 6); + hlen = parse_pes_header(t, st, + st->st_buf.sb_data + 6, st->st_buf.sb_ptr - 6); if(hlen < 0) return; st->st_parser_ptr += 6 + hlen; @@ -317,15 +305,15 @@ parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data, p = st->st_parser_ptr; - while((l = st->st_buffer_ptr - p) > 3) { - if(st->st_buffer[p] == 0x56 && (st->st_buffer[p + 1] & 0xe0) == 0xe0) { - muxlen = (st->st_buffer[p + 1] & 0x1f) << 8 | - st->st_buffer[p + 2]; + while((l = st->st_buf.sb_ptr - p) > 3) { + const uint8_t *d = st->st_buf.sb_data + p; + if(d[0] == 0x56 && (d[1] & 0xe0) == 0xe0) { + muxlen = (d[1] & 0x1f) << 8 | d[2]; if(l < muxlen + 3) break; - pkt = parse_latm_audio_mux_element(t, st, st->st_buffer + p + 3, muxlen); + pkt = parse_latm_audio_mux_element(t, st, d + 3, muxlen); if(pkt != NULL) parser_deliver(t, st, pkt); @@ -354,8 +342,7 @@ parse_sc(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, { uint32_t sc = st->st_startcond; int i, r; - - buffer_alloc(st, len); + sbuf_alloc(&st->st_buf, len); for(i = 0; i < len; i++) { @@ -378,20 +365,20 @@ parse_sc(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, continue; } - st->st_buffer[st->st_buffer_ptr++] = data[i]; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = data[i]; sc = sc << 8 | data[i]; if((sc & 0xffffff00) != 0x00000100) continue; - r = st->st_buffer_ptr - st->st_startcode_offset - 4; + r = st->st_buf.sb_ptr - st->st_startcode_offset - 4; if(r > 0 && st->st_startcode != 0) { r = vp(t, st, r, sc, st->st_startcode_offset); if(r == 3) continue; if(r == 4) { - st->st_buffer_ptr -= 4; + st->st_buf.sb_ptr -= 4; st->st_ssc_intercept = 1; st->st_ssc_ptr = 0; sc = -1; @@ -403,27 +390,26 @@ parse_sc(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, if(r == 2) { // Drop packet - st->st_buffer_ptr = st->st_startcode_offset; + st->st_buf.sb_ptr = st->st_startcode_offset; - st->st_buffer[st->st_buffer_ptr++] = sc >> 24; - st->st_buffer[st->st_buffer_ptr++] = sc >> 16; - st->st_buffer[st->st_buffer_ptr++] = sc >> 8; - st->st_buffer[st->st_buffer_ptr++] = sc; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 24; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 16; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 8; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc; st->st_startcode = sc; } else { if(r == 1) { /* Reset packet parser upon length error or if parser tells us so */ - st->st_buffer_ptr = 0; - st->st_buffer_errors = 0; - st->st_buffer[st->st_buffer_ptr++] = sc >> 24; - st->st_buffer[st->st_buffer_ptr++] = sc >> 16; - st->st_buffer[st->st_buffer_ptr++] = sc >> 8; - st->st_buffer[st->st_buffer_ptr++] = sc; + sbuf_reset(&st->st_buf); + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 24; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 16; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc >> 8; + st->st_buf.sb_data[st->st_buf.sb_ptr++] = sc; } st->st_startcode = sc; - st->st_startcode_offset = st->st_buffer_ptr - 4; + st->st_startcode_offset = st->st_buf.sb_ptr - 4; } } st->st_startcond = sc; @@ -437,7 +423,7 @@ static int depacketize(th_transport_t *t, th_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { - const uint8_t *buf = st->st_buffer + sc_offset; + const uint8_t *buf = st->st_buf.sb_data + sc_offset; uint32_t sc = st->st_startcode; int hlen, plen; @@ -463,7 +449,7 @@ depacketize(th_transport_t *t, th_stream_t *st, size_t len, buf += hlen; len -= hlen; - buffer3_append(st, buf, len); + sbuf_append(&st->st_buf_a, buf, len); return 0; } @@ -521,8 +507,8 @@ parse_mpa(th_transport_t *t, th_stream_t *st, size_t ilen, return i; again: - buf = st->st_buffer3; - len = st->st_buffer3_ptr; + buf = st->st_buf_a.sb_data; + len = st->st_buf_a.sb_ptr; for(i = 0; i < len - 4; i++) { if(mpa_valid_frame(buf + i)) { @@ -544,7 +530,7 @@ parse_mpa(th_transport_t *t, th_stream_t *st, size_t ilen, makeapkt(t, st, buf + i, fsize, dts, duration, channels, mpa_sri[(buf[i+2] >> 2) & 3]); - buffer3_cut(st, i + fsize); + sbuf_cut(&st->st_buf_a, i + fsize); goto again; } } @@ -634,8 +620,8 @@ parse_ac3(th_transport_t *t, th_stream_t *st, size_t ilen, return i; again: - buf = st->st_buffer3; - len = st->st_buffer3_ptr; + buf = st->st_buf_a.sb_data; + len = st->st_buf_a.sb_ptr; for(i = 0; i < len - 6; i++) { const uint8_t *p = buf + i; @@ -677,7 +663,7 @@ parse_ac3(th_transport_t *t, th_stream_t *st, size_t ilen, ac3_valid_frame(p + fsize)) { bitstream_t bs; - init_bits(&bs, (uint8_t *)p + 5, (fsize - 5) * 8); + init_rbits(&bs, p + 5, (fsize - 5) * 8); read_bits(&bs, 5); // bsid read_bits(&bs, 3); // bsmod @@ -694,7 +680,7 @@ parse_ac3(th_transport_t *t, th_stream_t *st, size_t ilen, int channels = acmodtab[acmod] + lfeon; makeapkt(t, st, p, fsize, dts, duration, channels, sri); - buffer3_cut(st, i + fsize); + sbuf_cut(&st->st_buf_a, i + fsize); goto again; } } @@ -744,7 +730,7 @@ parse_pes_header(th_transport_t *t, th_stream_t *st, } else return hlen + 3; - if(st->st_buffer_errors) { + if(st->st_buf.sb_err) { st->st_curdts = PTS_UNSET; st->st_curpts = PTS_UNSET; } else { @@ -889,7 +875,7 @@ parser_global_data_move(th_stream_t *st, const uint8_t *data, size_t len) memcpy(st->st_global_data + st->st_global_data_len, data, len2); st->st_global_data_len += len2; - st->st_buffer_ptr -= len; + st->st_buf.sb_ptr -= len; } @@ -907,14 +893,14 @@ static int parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { - uint8_t *buf = st->st_buffer + sc_offset; + const uint8_t *buf = st->st_buf.sb_data + sc_offset; bitstream_t bs; int frametype; if(next_startcode == 0x1e0) return 4; - init_bits(&bs, buf + 4, (len - 4) * 8); + init_rbits(&bs, buf + 4, (len - 4) * 8); switch(st->st_startcode) { case 0x000001e0 ... 0x000001ef: @@ -944,7 +930,7 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len, case 0x000001b3: /* Sequence start code */ - if(!st->st_buffer_errors) { + if(!st->st_buf.sb_err) { if(parse_mpeg2video_seq_start(t, st, &bs)) return 1; parser_global_data_move(st, buf, len); @@ -957,12 +943,12 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len, switch(buf[4] >> 4) { case 0x1: // Sequence Extension - if(!st->st_buffer_errors) + if(!st->st_buf.sb_err) parser_global_data_move(st, buf, len); return 2; case 0x2: // Sequence Display Extension - if(!st->st_buffer_errors) + if(!st->st_buf.sb_err) parser_global_data_move(st, buf, len); return 2; } @@ -986,13 +972,14 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len, st->st_global_data_len = 0; } - pkt->pkt_payload = pktbuf_make(st->st_buffer, st->st_buffer_ptr - 4); + pkt->pkt_payload = pktbuf_make(st->st_buf.sb_data, + st->st_buf.sb_ptr - 4); pkt->pkt_duration = st->st_frame_duration; parser_deliver(t, st, pkt); st->st_curpkt = NULL; - st->st_buffer = malloc(st->st_buffer_size); + st->st_buf.sb_data = malloc(st->st_buf.sb_size); /* If we know the frame duration, increase DTS accordingly */ if(st->st_curdts != PTS_UNSET) @@ -1006,7 +993,7 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len, case 0x000001b8: // GOP header - if(!st->st_buffer_errors) + if(!st->st_buf.sb_err) parser_global_data_move(st, buf, len); return 2; @@ -1029,7 +1016,7 @@ static int parse_h264(th_transport_t *t, th_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { - uint8_t *buf = st->st_buffer + sc_offset; + const uint8_t *buf = st->st_buf.sb_data + sc_offset; uint32_t sc = st->st_startcode; int64_t d; int l2, pkttype, duration, isfield; @@ -1051,12 +1038,10 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, return 1; } - bs.data = NULL; - if(sc == 0x10c) { // Padding - st->st_buffer_ptr -= len; + st->st_buf.sb_ptr -= len; ret = 2; } else { @@ -1064,18 +1049,20 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, switch(sc & 0x1f) { case 7: - if(!st->st_buffer_errors) { - h264_nal_deescape(&bs, buf + 3, len - 3); + if(!st->st_buf.sb_err) { + void *f = h264_nal_deescape(&bs, buf + 3, len - 3); h264_decode_seq_parameter_set(st, &bs); + free(f); parser_global_data_move(st, buf, len); } ret = 2; break; case 8: - if(!st->st_buffer_errors) { - h264_nal_deescape(&bs, buf + 3, len - 3); + if(!st->st_buf.sb_err) { + void *f = h264_nal_deescape(&bs, buf + 3, len - 3); h264_decode_pic_parameter_set(st, &bs); + free(f); parser_global_data_move(st, buf, len); } ret = 2; @@ -1087,12 +1074,14 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, break; l2 = len - 3 > 64 ? 64 : len - 3; - h264_nal_deescape(&bs, buf + 3, l2); /* we just want the first stuff */ + void *f = h264_nal_deescape(&bs, buf + 3, l2); + /* we just want the first stuff */ if(h264_decode_slice_header(st, &bs, &pkttype, &duration, &isfield)) { - free(bs.data); + free(f); return 1; } + free(f); st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts); st->st_curpkt->pkt_frametype = pkttype; @@ -1105,7 +1094,6 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, break; } } - free(bs.data); if(next_startcode >= 0x000001e0 && next_startcode <= 0x000001ef) { /* Complete frame */ @@ -1121,11 +1109,12 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, st->st_global_data_len = 0; } - pkt->pkt_payload = pktbuf_make(st->st_buffer, st->st_buffer_ptr - 4); + pkt->pkt_payload = pktbuf_make(st->st_buf.sb_data, + st->st_buf.sb_ptr - 4); parser_deliver(t, st, pkt); st->st_curpkt = NULL; - st->st_buffer = malloc(st->st_buffer_size); + st->st_buf.sb_data = malloc(st->st_buf.sb_size); st->st_curdts = PTS_UNSET; st->st_curpts = PTS_UNSET; @@ -1145,46 +1134,42 @@ parse_subtitles(th_transport_t *t, th_stream_t *st, const uint8_t *data, { th_pkt_t *pkt; int psize, hlen; - uint8_t *buf; - + const uint8_t *buf; + const uint8_t *d; if(start) { /* Payload unit start */ st->st_parser_state = 1; - st->st_buffer_errors = 0; + st->st_buf.sb_err = 0; } if(st->st_parser_state == 0) return; - buffer_append(st, data, len); + sbuf_append(&st->st_buf, data, len); - if(st->st_buffer_ptr < 6) + if(st->st_buf.sb_ptr < 6) return; - - uint32_t startcode = - (st->st_buffer[0] << 24) | - (st->st_buffer[1] << 16) | - (st->st_buffer[2] << 8) | - (st->st_buffer[3]); + d = st->st_buf.sb_data; + uint32_t startcode = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; if(startcode == 0x1be) { st->st_parser_state = 0; return; } - psize = st->st_buffer[4] << 8 | st->st_buffer[5]; + psize = d[4] << 8 | d[5]; - if(st->st_buffer_ptr != psize + 6) + if(st->st_buf.sb_ptr != psize + 6) return; st->st_parser_state = 0; - hlen = parse_pes_header(t, st, st->st_buffer + 6, st->st_buffer_ptr - 6); + hlen = parse_pes_header(t, st, d + 6, st->st_buf.sb_ptr - 6); if(hlen < 0) return; psize -= hlen; - buf = st->st_buffer + 6 + hlen; + buf = d + 6 + hlen; if(psize < 2 || buf[0] != 0x20 || buf[1] != 0x00) return; diff --git a/src/transports.c b/src/transports.c index b4a90e78..44fc0f87 100644 --- a/src/transports.c +++ b/src/transports.c @@ -92,22 +92,10 @@ stream_clean(th_stream_t *st) /* Clear reassembly buffers */ st->st_startcode = 0; - - free(st->st_buffer); - st->st_buffer = NULL; - st->st_buffer_size = 0; - st->st_buffer_ptr = 0; - - free(st->st_buffer2); - st->st_buffer2 = NULL; - st->st_buffer2_size = 0; - st->st_buffer2_ptr = 0; - - free(st->st_buffer3); - st->st_buffer3 = NULL; - st->st_buffer3_size = 0; - st->st_buffer3_ptr = 0; - + + sbuf_free(&st->st_buf); + sbuf_free(&st->st_buf_ps); + sbuf_free(&st->st_buf_a); if(st->st_curpkt != NULL) { pkt_ref_dec(st->st_curpkt); diff --git a/src/tvhead.h b/src/tvhead.h index 812b4ff6..d01e36bd 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -313,6 +313,17 @@ typedef struct streaming_queue { } streaming_queue_t; +/** + * Simple dynamically growing buffer + */ +typedef struct sbuf { + uint8_t *sb_data; + int sb_ptr; + int sb_size; + int sb_err; +} sbuf_t; + + /** * Descrambler superclass @@ -401,10 +412,7 @@ typedef struct th_stream { /* For transport stream packet reassembly */ - uint8_t *st_buffer; - int st_buffer_ptr; - int st_buffer_size; - int st_buffer_errors; /* Errors accumulated for this packet */ + sbuf_t st_buf; uint32_t st_startcond; uint32_t st_startcode; @@ -413,13 +421,8 @@ typedef struct th_stream { int st_parser_ptr; void *st_priv; /* Parser private data */ - uint8_t *st_buffer2; - int st_buffer2_ptr; - int st_buffer2_size; - - uint8_t *st_buffer3; - int st_buffer3_ptr; - int st_buffer3_size; + sbuf_t st_buf_ps; // program stream reassembly (analogue adapters) + sbuf_t st_buf_a; // Audio packet reassembly uint8_t *st_global_data; int st_global_data_len; @@ -853,4 +856,16 @@ static inline int64_t ts_rescale(int64_t ts, int tb) return (ts * tb ) / 90000LL; } +void sbuf_free(sbuf_t *sb); + +void sbuf_reset(sbuf_t *sb); + +void sbuf_err(sbuf_t *sb); + +void sbuf_alloc(sbuf_t *sb, int len); + +void sbuf_append(sbuf_t *sb, const uint8_t *data, int len); + +void sbuf_cut(sbuf_t *sb, int off); + #endif /* TV_HEAD_H */ diff --git a/src/utils.c b/src/utils.c index e3975f12..8619554a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -18,6 +18,7 @@ */ #include +#include #include #include "tvhead.h" @@ -224,3 +225,55 @@ put_utf8(char *out, int c) *out++ = 0x80 | (0x3f & c); return 6; } + + + +void +sbuf_free(sbuf_t *sb) +{ + free(sb->sb_data); + sb->sb_size = sb->sb_ptr = sb->sb_err = 0; +} + +void +sbuf_reset(sbuf_t *sb) +{ + sb->sb_ptr = 0; + sb->sb_err = 0; +} + +void +sbuf_err(sbuf_t *sb) +{ + sb->sb_err = 1; +} + +void +sbuf_alloc(sbuf_t *sb, int len) +{ + if(sb->sb_data == NULL) { + sb->sb_size = 4000; + sb->sb_data = malloc(sb->sb_size); + } + + if(sb->sb_ptr + len >= sb->sb_size) { + sb->sb_size += len * 4; + sb->sb_data = realloc(sb->sb_data, sb->sb_size); + } +} + +void +sbuf_append(sbuf_t *sb, const uint8_t *data, int len) +{ + sbuf_alloc(sb, len); + memcpy(sb->sb_data + sb->sb_ptr, data, len); + sb->sb_ptr += len; +} + +void +sbuf_cut(sbuf_t *sb, int off) +{ + assert(off <= sb->sb_ptr); + sb->sb_ptr = sb->sb_ptr - off; + memmove(sb->sb_data, sb->sb_data + off, sb->sb_ptr); +} diff --git a/src/v4l.c b/src/v4l.c index 0754079e..01921f59 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -87,36 +87,36 @@ v4l_input(v4l_adapter_t *va) } if(va->va_lenlock == 2) { - l = st->st_buffer2_size; - st->st_buffer2 = pkt = realloc(st->st_buffer2, l); + l = st->st_buf_ps.sb_size; + st->st_buf_ps.sb_data = pkt = realloc(st->st_buf_ps.sb_data, l); - r = l - st->st_buffer2_ptr; + r = l - st->st_buf_ps.sb_ptr; if(r > len) r = len; - memcpy(pkt + st->st_buffer2_ptr, ptr, r); + memcpy(pkt + st->st_buf_ps.sb_ptr, ptr, r); ptr += r; len -= r; - st->st_buffer2_ptr += r; - if(st->st_buffer2_ptr == l) { + st->st_buf_ps.sb_ptr += r; + if(st->st_buf_ps.sb_ptr == l) { transport_set_streaming_status_flags(t, TSS_MUX_PACKETS); parse_mpeg_ps(t, st, pkt + 6, l - 6); - st->st_buffer2_size = 0; + st->st_buf_ps.sb_size = 0; va->va_startcode = 0; } else { - assert(st->st_buffer2_ptr < l); + assert(st->st_buf_ps.sb_ptr < l); } } else { - st->st_buffer2_size = st->st_buffer2_size << 8 | *ptr; + st->st_buf_ps.sb_size = st->st_buf_ps.sb_size << 8 | *ptr; va->va_lenlock++; if(va->va_lenlock == 2) { - st->st_buffer2_size += 6; - st->st_buffer2_ptr = 6; + st->st_buf_ps.sb_size += 6; + st->st_buf_ps.sb_ptr = 6; } ptr++; len--; }