diff --git a/src/parser_h264.c b/src/parser_h264.c index 180cc483..7a7efc41 100644 --- a/src/parser_h264.c +++ b/src/parser_h264.c @@ -90,10 +90,15 @@ static const int h264_lev2cpbsize[][2] = { typedef struct h264_private { struct { - int frame_duration; int cbpsize; int16_t width; int16_t height; + int16_t max_frame_num_bits; + char mbs_only_flag; + char aff; + char fixed_rate; + int units_in_tick; + int time_scale; } sps[256]; struct { @@ -106,13 +111,8 @@ typedef struct h264_private { static int -decode_vui(th_stream_t *st, bitstream_t *bs, int spsid) +decode_vui(h264_private_t *p, bitstream_t *bs, int sps_id) { - int units_in_tick; - int time_scale; - int fixed_rate; - return 0; - if(read_bits1(bs)) { if(read_bits(bs, 8) == 255) { read_bits(bs, 16); @@ -140,16 +140,12 @@ decode_vui(th_stream_t *st, bitstream_t *bs, int spsid) } if(!read_bits1(bs)) /* We need timing info */ - return -1; + return 0; - units_in_tick = read_bits(bs, 32); - time_scale = read_bits(bs, 32); - fixed_rate = read_bits1(bs); -#if 0 - printf("units_in_tick = %d\n", units_in_tick); - printf("time_scale = %d\n", time_scale); - printf("fixed_rate = %d\n", fixed_rate); -#endif + + p->sps[sps_id].units_in_tick = read_bits(bs, 32); + p->sps[sps_id].time_scale = read_bits(bs, 32); + p->sps[sps_id].fixed_rate = read_bits1(bs); return 0; } @@ -229,7 +225,7 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs) } } - tmp = read_golomb_ue(bs); /* max frame num */ + p->sps[sps_id].max_frame_num_bits = read_golomb_ue(bs) + 4; poc_type= read_golomb_ue(bs); if(poc_type == 0){ //FIXME #define @@ -257,8 +253,9 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs) p->sps[sps_id].width = width * 16; p->sps[sps_id].height = height * 16; - if(!read_bits1(bs)) - read_bits1(bs); + p->sps[sps_id].mbs_only_flag = read_bits1(bs); + if(!p->sps[sps_id].mbs_only_flag) + p->sps[sps_id].aff = read_bits1(bs); read_bits1(bs); @@ -271,7 +268,7 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs) } if(read_bits1(bs)) { - decode_vui(st, bs, sps_id); + decode_vui(p, bs, sps_id); return 0; } else { return -1; @@ -296,10 +293,11 @@ h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs) int -h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype) +h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype, + int *duration) { h264_private_t *p; - int slice_type, pps_id, sps_id; + int slice_type, pps_id, sps_id, fnum; if((p = st->st_priv) == NULL) return -1; @@ -326,11 +324,39 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype) pps_id = read_golomb_ue(bs); sps_id = p->pps[pps_id].sps; - if(p->sps[sps_id].cbpsize == 0) + if(p->sps[sps_id].max_frame_num_bits == 0) return -1; - st->st_vbv_size = p->sps[sps_id].cbpsize; + fnum = read_bits(bs, p->sps[sps_id].max_frame_num_bits); + + int structure; + + int timebase = 180000; + + if(p->sps[sps_id].mbs_only_flag) { + structure = 0; + } else { + if(read_bits1(bs)) { + read_bits1(bs); // bottom field + structure = 1; + } else { + structure = 2; + } + } + + if(p->sps[sps_id].time_scale != 0) { + int d = timebase * p->sps[sps_id].units_in_tick / p->sps[sps_id].time_scale; + *duration = d; + } else { + *duration = 0; + } + + if(p->sps[sps_id].cbpsize != 0) + st->st_vbv_size = p->sps[sps_id].cbpsize; + st->st_vbv_delay = -1; - parser_set_stream_meta(st, p->sps[sps_id].width, p->sps[sps_id].height, 0); + + if(p->sps[sps_id].width && p->sps[sps_id].height) + 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 e76f42f3..d0c7e751 100644 --- a/src/parser_h264.h +++ b/src/parser_h264.h @@ -27,6 +27,7 @@ int h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs); int h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs); -int h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype); +int h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype, + int *duration); #endif /* PARSER_H264_H_ */ diff --git a/src/parsers.c b/src/parsers.c index 59f3915f..04ff447c 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -630,17 +630,15 @@ parse_mpeg2video_pic_start(th_transport_t *t, th_stream_t *st, int *frametype, * */ void -parser_set_stream_meta(th_stream_t *st, int width, int height, int d) +parser_set_stream_vsize(th_stream_t *st, int width, int height) { int need_save = 0; - if(st->st_frame_duration == 0 && st->st_width == 0 && st->st_height == 0) { + if(st->st_width == 0 && st->st_height == 0) { need_save = 1; st->st_meta_change = 0; - } else if((d && st->st_frame_duration != d) || - st->st_width != width || - st->st_height != height) { + } else if(st->st_width != width || st->st_height != height) { st->st_meta_change++; if(st->st_meta_change == 2) @@ -651,8 +649,6 @@ parser_set_stream_meta(th_stream_t *st, int width, int height, int d) } if(need_save) { - if(d) - st->st_frame_duration = d; st->st_width = width; st->st_height = height; transport_request_save(st->st_transport, 1); @@ -667,7 +663,7 @@ static int parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st, bitstream_t *bs) { - int v, width, height, d; + int v, width, height; if(bs->len < 61) return 1; @@ -675,7 +671,7 @@ parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st, width = read_bits(bs, 12); height = read_bits(bs, 12); skip_bits(bs, 4); - d = mpeg2video_framedurations[read_bits(bs, 4)]; + st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)]; v = read_bits(bs, 18) * 400; skip_bits(bs, 1); @@ -683,7 +679,7 @@ parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st, v = read_bits(bs, 10) * 16 * 1024 / 8; st->st_vbv_size = v; - parser_set_stream_meta(st, width, height, d); + parser_set_stream_vsize(st, width, height); return 0; } @@ -835,7 +831,7 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, uint8_t *buf = st->st_buffer + sc_offset; uint32_t sc = st->st_startcode; int64_t d; - int l2, pkttype; + int l2, pkttype, duration; bitstream_t bs; int ret = 0; @@ -892,14 +888,16 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, l2 = len - 3 > 64 ? 64 : len - 3; h264_nal_deescape(&bs, buf + 3, l2); /* we just want the first stuff */ - if(h264_decode_slice_header(st, &bs, &pkttype)) { + duration = 0; + + if(h264_decode_slice_header(st, &bs, &pkttype, &duration)) { free(bs.data); return 1; } st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts); st->st_curpkt->pkt_frametype = pkttype; - st->st_curpkt->pkt_duration = st->st_frame_duration; + st->st_curpkt->pkt_duration = duration ?: st->st_frame_duration; st->st_curpkt->pkt_commercial = t->tht_tt_commercial_advice; break; diff --git a/src/parsers.h b/src/parsers.h index 42bca984..ff7b6fcc 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -28,7 +28,7 @@ void parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len); void parser_enqueue_packet(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt); -void parser_set_stream_meta(th_stream_t *st, int width, int height, int d); +void parser_set_stream_vsize(th_stream_t *st, int width, int height); extern const unsigned int mpeg2video_framedurations[16]; diff --git a/src/psi.c b/src/psi.c index 0db404b1..664d13a7 100644 --- a/src/psi.c +++ b/src/psi.c @@ -422,7 +422,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, streaming_component_type_t hts_stream_type; th_stream_t *st, *next; char lang[4]; - int frameduration; int update = 0; int had_components; int composition_id; @@ -502,7 +501,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, ptr += 5; len -= 5; - frameduration = 0; hts_stream_type = SCT_UNKNOWN; memset(lang, 0, 4); composition_id = -1; @@ -551,10 +549,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, hts_stream_type = SCT_AC3; break; - case DVB_DESC_VIDEO_STREAM: - frameduration = mpeg2video_framedurations[(ptr[0] >> 3) & 0xf]; - break; - case DVB_DESC_LANGUAGE: memcpy(lang, ptr, 3); break; @@ -618,11 +612,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, memcpy(st->st_lang, lang, 4); } - if(st->st_frame_duration == 0 && frameduration != 0) { - st->st_frame_duration = frameduration; - update |= PMT_UPDATE_FRAME_DURATION; - } - if(composition_id != -1 && st->st_composition_id != composition_id) { st->st_composition_id = composition_id; update |= PMT_UPDATE_COMPOSITION_ID; @@ -980,9 +969,6 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t) if(st->st_type == SCT_TEXTSUB) htsmsg_add_u32(sub, "parentpid", st->st_parent_pid); - if(st->st_frame_duration) - htsmsg_add_u32(sub, "frameduration", st->st_frame_duration); - if(st->st_type == SCT_MPEG2VIDEO || st->st_type == SCT_H264) { if(st->st_width && st->st_height) { htsmsg_add_u32(sub, "width", st->st_width); @@ -1106,9 +1092,6 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t) if((v = htsmsg_get_str(c, "language")) != NULL) av_strlcpy(st->st_lang, v, 4); - if(!htsmsg_get_u32(c, "frameduration", &u32)) - st->st_frame_duration = u32; - if(!htsmsg_get_u32(c, "position", &u32)) st->st_position = u32;