/* * Packet parsing functions * Copyright (C) 2007 Andreas Öman * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "tvheadend.h" #include "service.h" #include "parsers.h" #include "parser_h264.h" #include "parser_latm.h" #include "bitstream.h" #include "packet.h" #include "streaming.h" #define PTS_MASK 0x1ffffffffLL //#define PTS_MASK 0x7ffffLL #define getu32(b, l) ({ \ uint32_t x = (b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]); \ b+=4; \ l-=4; \ x; \ }) #define getu16(b, l) ({ \ uint16_t x = (b[0] << 8 | b[1]); \ b+=2; \ l-=2; \ x; \ }) #define getu8(b, l) ({ \ uint8_t x = b[0]; \ b+=1; \ l-=1; \ x; \ }) static int64_t getpts(const uint8_t *p) { int a = p[0]; int b = (p[1] << 8) | p[2]; int c = (p[3] << 8) | p[4]; if((a & 1) && (b & 1) && (c & 1)) { return ((int64_t)((a >> 1) & 0x07) << 30) | ((int64_t)((b >> 1) ) << 15) | ((int64_t)((c >> 1) )) ; } else { // Marker bits not present return PTS_UNSET; } } static int parse_mpeg2video(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); static int parse_h264(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); typedef int (packet_parser_t)(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); typedef void (aparser_t)(service_t *t, elementary_stream_t *st, th_pkt_t *pkt); static void parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, packet_parser_t *vp); static void parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start); static void parse_subtitles(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start); static void parse_teletext(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start); static int parse_mpa(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); static int parse_mpa2(service_t *t, elementary_stream_t *st); static int parse_ac3(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); static int parse_eac3(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset); static int parse_mp4a(service_t *t, elementary_stream_t *st, size_t ilen, uint32_t next_startcode, int sc_offset); static void parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt, int errors); static int parse_pes_header(service_t *t, elementary_stream_t *st, const uint8_t *buf, size_t len); /** * Parse raw mpeg data */ void parse_mpeg_ts(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start, int err) { if(err) sbuf_err(&st->es_buf); switch(st->es_type) { case SCT_MPEG2VIDEO: parse_sc(t, st, data, len, parse_mpeg2video); break; case SCT_H264: parse_sc(t, st, data, len, parse_h264); break; case SCT_MPEG2AUDIO: parse_sc(t, st, data, len, parse_mpa); break; case SCT_AC3: parse_sc(t, st, data, len, parse_ac3); break; case SCT_EAC3: parse_sc(t, st, data, len, parse_eac3); break; case SCT_MP4A: parse_sc(t, st, data, len, parse_mp4a); break; case SCT_DVBSUB: parse_subtitles(t, st, data, len, start); break; case SCT_AAC: parse_aac(t, st, data, len, start); break; case SCT_TELETEXT: parse_teletext(t, st, data, len, start); break; default: break; } } /** * Parse program stream, as from V4L2, etc. * * Note: data does not include startcode and packet length */ void parse_mpeg_ps(service_t *t, elementary_stream_t *st, uint8_t *data, int len) { int hlen; hlen = parse_pes_header(t, st, data, len); #if 0 int i; for(i = 0; i < 16; i++) printf("%02x.", data[i]); printf(" %d\n", hlen); #endif data += hlen; len -= hlen; if(len < 1) return; switch(st->es_type) { case SCT_MPEG2AUDIO: sbuf_append(&st->es_buf_a, data, len); parse_mpa2(t, st); break; case SCT_MPEG2VIDEO: parse_sc(t, st, data, len, parse_mpeg2video); break; default: break; } } /** * Parse AAC LATM */ static void parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start) { int l, muxlen, p; th_pkt_t *pkt; if(start) { /* Payload unit start */ st->es_parser_state = 1; st->es_parser_ptr = 0; sbuf_reset(&st->es_buf); } if(st->es_parser_state == 0) return; sbuf_append(&st->es_buf, data, len); if(st->es_parser_ptr == 0) { int hlen; if(st->es_buf.sb_ptr < 9) return; hlen = parse_pes_header(t, st, st->es_buf.sb_data + 6, st->es_buf.sb_ptr - 6); if(hlen < 0) return; st->es_parser_ptr += 6 + hlen; } p = st->es_parser_ptr; while((l = st->es_buf.sb_ptr - p) > 3) { const uint8_t *d = st->es_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, d + 3, muxlen); if(pkt != NULL) parser_deliver(t, st, pkt, st->es_buf.sb_err); p += muxlen + 3; } else { p++; } } st->es_parser_ptr = p; } /** * Generic video parser * * We scan for startcodes a'la 0x000001xx and let a specific parser * derive further information. */ static void parse_sc(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, packet_parser_t *vp) { uint32_t sc = st->es_startcond; int i, r; sbuf_alloc(&st->es_buf, len); for(i = 0; i < len; i++) { if(st->es_ssc_intercept == 1) { if(st->es_ssc_ptr < sizeof(st->es_ssc_buf)) st->es_ssc_buf[st->es_ssc_ptr] = data[i]; st->es_ssc_ptr++; if(st->es_ssc_ptr < 5) continue; uint16_t plen = st->es_ssc_buf[0] << 8 | st->es_ssc_buf[1]; st->es_incomplete = plen >= 0xffdf; int hlen = st->es_ssc_buf[4]; if(st->es_ssc_ptr < hlen + 5) continue; parse_pes_header(t, st, st->es_ssc_buf + 2, hlen + 3); st->es_ssc_intercept = 0; if(st->es_buf.sb_ptr > 2) sc = st->es_buf.sb_data[st->es_buf.sb_ptr-3] << 16 | st->es_buf.sb_data[st->es_buf.sb_ptr-2] << 8 | st->es_buf.sb_data[st->es_buf.sb_ptr-1]; continue; } st->es_buf.sb_data[st->es_buf.sb_ptr++] = data[i]; sc = sc << 8 | data[i]; if((sc & 0xffffff00) != 0x00000100) continue; if(sc == 0x100 && (len-i)>3) { uint32_t tempsc = data[i+1] << 16 | data[i+2] << 8 | data[i+3]; if(tempsc == 0x1e0) continue; } r = st->es_buf.sb_ptr - st->es_startcode_offset - 4; if(r > 0 && st->es_startcode != 0) { r = vp(t, st, r, sc, st->es_startcode_offset); if(r == 3) continue; if(r == 4) { st->es_buf.sb_ptr -= 4; st->es_ssc_intercept = 1; st->es_ssc_ptr = 0; sc = -1; continue; } } else { r = 1; } assert(st->es_buf.sb_data != NULL); if(r == 2) { // Drop packet st->es_buf.sb_ptr = st->es_startcode_offset; 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; st->es_startcode = sc; } else { if(r == 1) { /* Reset packet parser upon length error or if parser tells us so */ sbuf_reset(&st->es_buf); 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; } st->es_startcode = sc; st->es_startcode_offset = st->es_buf.sb_ptr - 4; } } st->es_startcond = sc; } /** * */ static int depacketize(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { const uint8_t *buf = st->es_buf.sb_data + sc_offset; uint32_t sc = st->es_startcode; int hlen, plen; if((sc != 0x1bd && (sc & ~0x1f) != 0x1c0) || len < 9) return 1; plen = (buf[4] << 8) | buf[5]; if(plen + 6 > len || next_startcode != sc) return 3; if(plen + 6 < len) return 1; buf += 6; len -= 6; hlen = parse_pes_header(t, st, buf, len); if(hlen < 0) return 1; buf += hlen; len -= hlen; st->es_buf_a.sb_err = st->es_buf.sb_err; sbuf_append(&st->es_buf_a, buf, len); return 0; } /** * */ static void makeapkt(service_t *t, elementary_stream_t *st, const void *buf, int len, int64_t dts, int duration, int channels, int sri, int errors) { th_pkt_t *pkt = pkt_alloc(buf, len, dts, dts); pkt->pkt_commercial = t->s_tt_commercial_advice; pkt->pkt_duration = duration; pkt->pkt_channels = channels; pkt->pkt_sri = sri; parser_deliver(t, st, pkt, errors); st->es_curdts = PTS_UNSET; st->es_nextdts = dts + duration; } /** * Parse AAC MP4A */ static const int aac_sample_rates[12] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 }; /** * Inspect ADTS header */ static int mp4a_valid_frame(const uint8_t *buf) { return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); } static int parse_mp4a(service_t *t, elementary_stream_t *st, size_t ilen, uint32_t next_startcode, int sc_offset) { int i, len; const uint8_t *buf; if((i = depacketize(t, st, ilen, next_startcode, sc_offset)) != 0) return i; again: buf = st->es_buf_a.sb_data; len = st->es_buf_a.sb_ptr; for(i = 0; i < len - 6; i++) { const uint8_t *p = buf + i; if(mp4a_valid_frame(p)) { int fsize = ((p[3] & 0x03) << 11) | (p[4] << 3) | ((p[5] & 0xe0) >> 5); int sr_index = (p[2] & 0x3c) >> 2; int sr = aac_sample_rates[sr_index]; if(sr && fsize) { int duration = 90000 * 1024 / sr; int64_t dts = st->es_curdts; int sri = rate_to_sri(sr); if(dts == PTS_UNSET) dts = st->es_nextdts; if(dts != PTS_UNSET && len >= i + fsize + 6 && mp4a_valid_frame(p + fsize)) { int channels = ((p[2] & 0x01) << 2) | ((p[3] & 0xc0) >> 6); makeapkt(t, st, p, fsize, dts, duration, channels, sri, st->es_buf_a.sb_err); st->es_buf_a.sb_err = 0; sbuf_cut(&st->es_buf_a, i + fsize); goto again; } } } } return 1; } const static int mpa_br[16] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }; const static int mpa_sr[4] = {44100, 48000, 32000, 0}; const static int mpa_sri[4] = {4, 3, 5, 0}; static int mpa_valid_frame(const uint8_t *buf) { return buf[0] == 0xff && (buf[1] & 0xfe) == 0xfc; } /** * */ static int parse_mpa2(service_t *t, elementary_stream_t *st) { int i, len; const uint8_t *buf; again: buf = st->es_buf_a.sb_data; len = st->es_buf_a.sb_ptr; for(i = 0; i < len - 4; i++) { if(mpa_valid_frame(buf + i)) { int br = mpa_br[ buf[i+2] >> 4 ]; int sr = mpa_sr[(buf[i+2] >> 2) & 3]; int pad = (buf[i+2] >> 1) & 1; if(br && sr) { int fsize = 144000 * br / sr + pad; int duration = 90000 * 1152 / sr; int64_t dts = st->es_curdts; int channels = (buf[i + 3] & 0xc0) == 0xc0 ? 1 : 2; if(dts == PTS_UNSET) dts = st->es_nextdts; if(dts != PTS_UNSET && len >= i + fsize + 4 && mpa_valid_frame(buf + i + fsize)) { makeapkt(t, st, buf + i, fsize, dts, duration, channels, mpa_sri[(buf[i+2] >> 2) & 3], st->es_buf_a.sb_err); st->es_buf_a.sb_err = 0; sbuf_cut(&st->es_buf_a, i + fsize); goto again; } } } } return 1; } /** * */ static int parse_mpa(service_t *t, elementary_stream_t *st, size_t ilen, uint32_t next_startcode, int sc_offset) { int r; if((r = depacketize(t, st, ilen, next_startcode, sc_offset)) != 0) return r; return parse_mpa2(t, st); } /** * AC3 audio parser */ const static int ac3_freq_tab[4] = {48000, 44100, 32000, 0}; const static uint16_t ac3_frame_size_tab[38][3] = { { 64, 69, 96 }, { 64, 70, 96 }, { 80, 87, 120 }, { 80, 88, 120 }, { 96, 104, 144 }, { 96, 105, 144 }, { 112, 121, 168 }, { 112, 122, 168 }, { 128, 139, 192 }, { 128, 140, 192 }, { 160, 174, 240 }, { 160, 175, 240 }, { 192, 208, 288 }, { 192, 209, 288 }, { 224, 243, 336 }, { 224, 244, 336 }, { 256, 278, 384 }, { 256, 279, 384 }, { 320, 348, 480 }, { 320, 349, 480 }, { 384, 417, 576 }, { 384, 418, 576 }, { 448, 487, 672 }, { 448, 488, 672 }, { 512, 557, 768 }, { 512, 558, 768 }, { 640, 696, 960 }, { 640, 697, 960 }, { 768, 835, 1152 }, { 768, 836, 1152 }, { 896, 975, 1344 }, { 896, 976, 1344 }, { 1024, 1114, 1536 }, { 1024, 1115, 1536 }, { 1152, 1253, 1728 }, { 1152, 1254, 1728 }, { 1280, 1393, 1920 }, { 1280, 1394, 1920 }, }; /** * Inspect 6 bytes AC3 header */ static int ac3_valid_frame(const uint8_t *buf) { if(buf[0] != 0x0b || buf[1] != 0x77 || buf[5] >> 3 > 10) return 0; return (buf[4] & 0xc0) != 0xc0 && (buf[4] & 0x3f) < 0x26; } static const char acmodtab[8] = {2,1,2,3,3,4,4,5}; static int parse_ac3(service_t *t, elementary_stream_t *st, size_t ilen, uint32_t next_startcode, int sc_offset) { int i, len; const uint8_t *buf; if((i = depacketize(t, st, ilen, next_startcode, sc_offset)) != 0) return i; again: buf = st->es_buf_a.sb_data; len = st->es_buf_a.sb_ptr; for(i = 0; i < len - 6; i++) { const uint8_t *p = buf + i; if(ac3_valid_frame(p)) { int bsid = p[5] >> 3; int fscod = p[4] >> 6; int frmsizcod = p[4] & 0x3f; int fsize = ac3_frame_size_tab[frmsizcod][fscod] * 2; bsid -= 8; if(bsid < 0) bsid = 0; int sr = ac3_freq_tab[fscod] >> bsid; if(sr) { int duration = 90000 * 1536 / sr; int64_t dts = st->es_curdts; int sri = rate_to_sri(sr); if(dts == PTS_UNSET) dts = st->es_nextdts; if(dts != PTS_UNSET && len >= i + fsize + 6 && ac3_valid_frame(p + fsize)) { bitstream_t bs; init_rbits(&bs, p + 5, (fsize - 5) * 8); read_bits(&bs, 5); // bsid read_bits(&bs, 3); // bsmod int acmod = read_bits(&bs, 3); if((acmod & 0x1) && (acmod != 0x1)) read_bits(&bs, 2); // cmixlen if(acmod & 0x4) read_bits(&bs, 2); // surmixlev if(acmod == 0x2) read_bits(&bs, 2); // dsurmod int lfeon = read_bits(&bs, 1); int channels = acmodtab[acmod] + lfeon; makeapkt(t, st, p, fsize, dts, duration, channels, sri, st->es_buf_a.sb_err); st->es_buf_a.sb_err = 0; sbuf_cut(&st->es_buf_a, i + fsize); goto again; } } } } return 1; } /** * EAC3 audio parser */ static int eac3_valid_frame(const uint8_t *buf) { if(buf[0] != 0x0b || buf[1] != 0x77 || buf[5] >> 3 <= 10) return 0; return (buf[4] & 0xc0) != 0xc0; } static int parse_eac3(service_t *t, elementary_stream_t *st, size_t ilen, uint32_t next_startcode, int sc_offset) { int i, len; const uint8_t *buf; if((i = depacketize(t, st, ilen, next_startcode, sc_offset)) != 0) return i; again: buf = st->es_buf_a.sb_data; len = st->es_buf_a.sb_ptr; for(i = 0; i < len - 6; i++) { const uint8_t *p = buf + i; if(eac3_valid_frame(p)) { int fsize = ((((p[2] & 0x7) << 8) + p[3]) + 1) * 2; int sr = p[4] >> 6; int rate; if(sr == 3) { int sr2 = (p[4] >> 4) & 0x3; if(sr2 == 3) continue; rate = ac3_freq_tab[sr2] / 2; } else { rate = ac3_freq_tab[sr]; } int64_t dts = st->es_curdts; int sri = rate_to_sri(rate); int acmod = (p[4] >> 1) & 0x7; int lfeon = p[4] & 1; int channels = acmodtab[acmod] + lfeon; int duration = 90000 * 1536 / rate; if(dts == PTS_UNSET) dts = st->es_nextdts; if(dts != PTS_UNSET && len >= i + fsize + 6 && eac3_valid_frame(p + fsize)) { makeapkt(t, st, p, fsize, dts, duration, channels, sri, st->es_buf_a.sb_err); st->es_buf_a.sb_err = 0; sbuf_cut(&st->es_buf_a, i + fsize); goto again; } } } return 1; } /** * PES header parser * * Extract DTS and PTS and update current values in stream */ static int parse_pes_header(service_t *t, elementary_stream_t *st, const uint8_t *buf, size_t len) { int64_t dts, pts, d; int hdr, flags, hlen; hdr = getu8(buf, len); flags = getu8(buf, len); hlen = getu8(buf, len); if(len < hlen || (hdr & 0xc0) != 0x80) goto err; if((flags & 0xc0) == 0xc0) { if(hlen < 10) goto err; pts = getpts(buf); dts = getpts(buf + 5); d = (pts - dts) & PTS_MASK; if(d > 180000) // More than two seconds of PTS/DTS delta, probably corrupt pts = dts = PTS_UNSET; } else if((flags & 0xc0) == 0x80) { if(hlen < 5) goto err; dts = pts = getpts(buf); } else return hlen + 3; if(st->es_buf.sb_err) { st->es_curdts = PTS_UNSET; st->es_curpts = PTS_UNSET; } else { st->es_curdts = dts; st->es_curpts = pts; } return hlen + 3; err: st->es_curdts = PTS_UNSET; st->es_curpts = PTS_UNSET; limitedlog(&st->es_loglimit_pes, "TS", service_component_nicename(st), "Corrupted PES header"); return -1; } /** * MPEG2VIDEO frame duration table (in 90kHz clock domain) */ const unsigned int mpeg2video_framedurations[16] = { 0, 3753, 3750, 3600, 3003, 3000, 1800, 1501, 1500, }; /** * Parse mpeg2video picture start */ static int parse_mpeg2video_pic_start(service_t *t, elementary_stream_t *st, int *frametype, bitstream_t *bs) { int v, pct; if(bs->len < 29) return 1; skip_bits(bs, 10); /* temporal reference */ pct = read_bits(bs, 3); if(pct < PKT_I_FRAME || pct > PKT_B_FRAME) return 1; /* Illegal picture_coding_type */ *frametype = pct; v = read_bits(bs, 16); /* vbv_delay */ if(v == 0xffff) st->es_vbv_delay = -1; else st->es_vbv_delay = v; return 0; } /** * */ void parser_set_stream_vsize(elementary_stream_t *st, int width, int height) { int need_save = 0; if(st->es_width == 0 && st->es_height == 0) { need_save = 1; st->es_meta_change = 0; } else if(st->es_width != width || st->es_height != height) { st->es_meta_change++; if(st->es_meta_change == 2) need_save = 1; } else { st->es_meta_change = 0; } if(need_save) { st->es_width = width; st->es_height = height; service_request_save(st->es_service, 1); } } static const uint8_t mpeg2_aspect[16][2]={ {0,1}, {1,1}, {4,3}, {16,9}, {221,100}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, }; /** * Parse mpeg2video sequence start */ static int parse_mpeg2video_seq_start(service_t *t, elementary_stream_t *st, bitstream_t *bs) { int v, width, height, aspect; if(bs->len < 61) return 1; width = read_bits(bs, 12); height = read_bits(bs, 12); aspect = read_bits(bs, 4); st->es_aspect_num = mpeg2_aspect[aspect][0]; st->es_aspect_den = mpeg2_aspect[aspect][1]; st->es_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)]; v = read_bits(bs, 18) * 400; skip_bits(bs, 1); v = read_bits(bs, 10) * 16 * 1024 / 8; st->es_vbv_size = v; parser_set_stream_vsize(st, width, height); return 0; } /** * */ static int drop_trailing_zeroes(const uint8_t *buf, size_t len) { while(len > 3 && (buf[len - 3] | buf[len - 2] | buf[len - 1]) == 0) len--; return len; } /** * */ static void parser_global_data_move(elementary_stream_t *st, const uint8_t *data, size_t len) { int len2 = drop_trailing_zeroes(data, len); st->es_global_data = realloc(st->es_global_data, st->es_global_data_len + len2); memcpy(st->es_global_data + st->es_global_data_len, data, len2); st->es_global_data_len += len2; st->es_buf.sb_ptr -= len; } /** * MPEG2VIDEO specific reassembly * * Process all startcodes (also the system ones) * * Extract framerate (or duration to be more specific) * * 'steal' the st->es_buffer and use it as 'pkt' buffer * */ static int parse_mpeg2video(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { const uint8_t *buf = st->es_buf.sb_data + sc_offset; bitstream_t bs; int frametype; if(next_startcode == 0x1e0) return 4; init_rbits(&bs, buf + 4, (len - 4) * 8); switch(st->es_startcode) { case 0x000001e0 ... 0x000001ef: /* System start codes for video */ if(len < 9) return 1; parse_pes_header(t, st, buf + 6, len - 6); return 1; case 0x00000100: /* Picture start code */ if(st->es_frame_duration == 0) return 1; if(parse_mpeg2video_pic_start(t, st, &frametype, &bs)) return 1; if(st->es_curpkt != NULL) pkt_ref_dec(st->es_curpkt); st->es_curpkt = pkt_alloc(NULL, 0, st->es_curpts, st->es_curdts); st->es_curpkt->pkt_frametype = frametype; st->es_curpkt->pkt_duration = st->es_frame_duration; st->es_curpkt->pkt_commercial = t->s_tt_commercial_advice; /* If we know the frame duration, increase DTS accordingly */ if(st->es_curdts != PTS_UNSET) st->es_curdts += st->es_frame_duration; /* PTS cannot be extrapolated (it's not linear) */ st->es_curpts = PTS_UNSET; break; case 0x000001b3: /* Sequence start code */ if(!st->es_buf.sb_err) { if(parse_mpeg2video_seq_start(t, st, &bs)) return 1; parser_global_data_move(st, buf, len); } return 2; case 0x000001b5: if(len < 5) return 1; switch(buf[4] >> 4) { case 0x1: // Sequence Extension if(!st->es_buf.sb_err) parser_global_data_move(st, buf, len); return 2; case 0x2: // Sequence Display Extension if(!st->es_buf.sb_err) parser_global_data_move(st, buf, len); return 2; } break; case 0x00000101 ... 0x000001af: /* Slices */ if(next_startcode == 0x100 || next_startcode > 0x1af) { /* Last picture slice (because next not a slice) */ th_pkt_t *pkt = st->es_curpkt; if(pkt == NULL) { /* no packet, may've been discarded by sanity checks here */ return 1; } if(st->es_global_data) { pkt->pkt_header = pktbuf_make(st->es_global_data, st->es_global_data_len); st->es_global_data = NULL; st->es_global_data_len = 0; } pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data, st->es_buf.sb_ptr - 4); pkt->pkt_duration = st->es_frame_duration; 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; case 0x000001b8: // GOP header if(!st->es_buf.sb_err) parser_global_data_move(st, buf, len); return 2; case 0x000001b2: // User data break; default: break; } return 0; } /** * H.264 parser */ static int parse_h264(service_t *t, elementary_stream_t *st, size_t len, uint32_t next_startcode, int sc_offset) { const uint8_t *buf = st->es_buf.sb_data + sc_offset; uint32_t sc = st->es_startcode; int64_t d; int l2, pkttype, duration, isfield; bitstream_t bs; int ret = 0; if(sc >= 0x000001e0 && sc <= 0x000001ef) { /* System start codes for video */ if(len >= 9){ uint16_t plen = buf[4] << 8 | buf[5]; if(plen >= 0xffe9) st->es_incomplete =1; parse_pes_header(t, st, buf + 6, len - 6); } if(st->es_prevdts != PTS_UNSET && st->es_curdts != PTS_UNSET) { d = (st->es_curdts - st->es_prevdts) & 0x1ffffffffLL; if(d < 90000) st->es_frame_duration = d; } st->es_prevdts = st->es_curdts; return 1; } if(sc == 0x10c) { // Padding st->es_buf.sb_ptr -= len; ret = 2; } else { switch(sc & 0x1f) { case 7: if(!st->es_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->es_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; break; case 5: /* IDR+SLICE */ case 1: if(st->es_curpkt != NULL || st->es_frame_duration == 0) break; l2 = len - 3 > 64 ? 64 : len - 3; 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(f); return 1; } free(f); st->es_curpkt = pkt_alloc(NULL, 0, st->es_curpts, st->es_curdts); st->es_curpkt->pkt_frametype = pkttype; st->es_curpkt->pkt_field = isfield; st->es_curpkt->pkt_duration = duration ?: st->es_frame_duration; st->es_curpkt->pkt_commercial = t->s_tt_commercial_advice; break; default: break; } } if(next_startcode >= 0x000001e0 && next_startcode <= 0x000001ef) { /* Complete frame */ if (st->es_incomplete) return 4; th_pkt_t *pkt = st->es_curpkt; if(pkt != NULL) { if(st->es_global_data) { pkt->pkt_header = pktbuf_make(st->es_global_data, st->es_global_data_len); st->es_global_data = NULL; st->es_global_data_len = 0; } pkt->pkt_payload = pktbuf_make(st->es_buf.sb_data, st->es_buf.sb_ptr - 4); 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; } return 1; } return ret; } /** * http://broadcasting.ru/pdf-standard-specifications/subtitling/dvb-sub/en300743.v1.2.1.pdf */ static void parse_subtitles(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start) { th_pkt_t *pkt; int psize, hlen; const uint8_t *buf; const uint8_t *d; if(start) { /* Payload unit start */ st->es_parser_state = 1; sbuf_reset(&st->es_buf); } if(st->es_parser_state == 0) return; sbuf_append(&st->es_buf, data, len); if(st->es_buf.sb_ptr < 6) return; d = st->es_buf.sb_data; uint32_t startcode = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; if(startcode == 0x1be) { st->es_parser_state = 0; return; } psize = d[4] << 8 | d[5]; if(st->es_buf.sb_ptr != psize + 6) return; st->es_parser_state = 0; hlen = parse_pes_header(t, st, d + 6, st->es_buf.sb_ptr - 6); if(hlen < 0) return; psize -= hlen; buf = d + 6 + hlen; if(psize < 2 || buf[0] != 0x20 || buf[1] != 0x00) return; psize -= 2; buf += 2; if(psize >= 6) { // end_of_PES_data_field_marker if(buf[psize - 1] == 0xff) { pkt = pkt_alloc(buf, psize - 1, st->es_curpts, st->es_curdts); pkt->pkt_commercial = t->s_tt_commercial_advice; parser_deliver(t, st, pkt, st->es_buf.sb_err); } } } /** * Teletext parser */ static void parse_teletext(service_t *t, elementary_stream_t *st, const uint8_t *data, int len, int start) { th_pkt_t *pkt; int psize, hlen; const uint8_t *buf; const uint8_t *d; if(start) { st->es_parser_state = 1; st->es_parser_ptr = 0; sbuf_reset(&st->es_buf); } if(st->es_parser_state == 0) return; sbuf_append(&st->es_buf, data, len); if(st->es_buf.sb_ptr < 6) return; d = st->es_buf.sb_data; psize = d[4] << 8 | d[5]; if(st->es_buf.sb_ptr != psize + 6) return; st->es_parser_state = 0; hlen = parse_pes_header(t, st, d + 6, st->es_buf.sb_ptr - 6); if(hlen < 0) return; psize -= hlen; buf = d + 6 + hlen; if(psize >= 46) { pkt = pkt_alloc(buf, psize, st->es_curpts, st->es_curdts); pkt->pkt_commercial = t->s_tt_commercial_advice; parser_deliver(t, st, pkt, st->es_buf.sb_err); } } /** * */ static void parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt, int error) { pkt->pkt_err = error; if(SCT_ISAUDIO(st->es_type) && pkt->pkt_pts != PTS_UNSET && (t->s_current_pts == PTS_UNSET || pkt->pkt_pts > t->s_current_pts || pkt->pkt_pts < t->s_current_pts - 180000)) t->s_current_pts = pkt->pkt_pts; #if 0 printf("PARSE: %-12s %d %10"PRId64" %10"PRId64" %10d %10d\n", streaming_component_type2txt(st->es_type), pkt->pkt_frametype, pkt->pkt_dts, pkt->pkt_pts, pkt->pkt_duration, pktbuf_len(pkt->pkt_payload)); #endif pkt->pkt_aspect_num = st->es_aspect_num; pkt->pkt_aspect_den = st->es_aspect_den; // avgstat_add(&st->es_rate, pkt->pkt_payloadlen, dispatch_clock); /** * Input is ok */ service_set_streaming_status_flags(t, TSS_PACKETS); /* Forward packet */ pkt->pkt_componentindex = st->es_index; streaming_message_t *sm = streaming_msg_create_pkt(pkt); streaming_pad_deliver(&t->s_streaming_pad, sm); streaming_msg_free(sm); /* Decrease our own reference to the packet */ pkt_ref_dec(pkt); }