From 4727974500a77336475def1adeac997dfa3953de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 24 Oct 2012 12:58:47 +0200 Subject: [PATCH] HTSP: Include video frame duration in streamingStart message --- src/htsp.c | 7 +++++-- src/parser_h264.c | 20 +++++++++----------- src/parser_h264.h | 2 +- src/parsers.c | 34 +++++++++++++++------------------- src/parsers.h | 3 ++- src/psi.c | 5 +++++ src/service.c | 1 + 7 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/htsp.c b/src/htsp.c index 4225b774..507f4973 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -1880,9 +1880,12 @@ htsp_subscription_start(htsp_subscription_t *hs, const streaming_start_t *ss) if(ssc->ssc_type == SCT_MPEG2VIDEO || ssc->ssc_type == SCT_H264) { if(ssc->ssc_width) - htsmsg_add_u32(c, "width", ssc->ssc_width); + htsmsg_add_u32(c, "width", ssc->ssc_width); if(ssc->ssc_height) - htsmsg_add_u32(c, "height", ssc->ssc_height); + htsmsg_add_u32(c, "height", ssc->ssc_height); + if(ssc->ssc_frameduration) + htsmsg_add_u32(c, "duration", hs->hs_90khz ? ssc->ssc_frameduration : + ts_rescale(ssc->ssc_frameduration, 1000000)); if (ssc->ssc_aspect_num) htsmsg_add_u32(c, "aspect_num", ssc->ssc_aspect_num); if (ssc->ssc_aspect_den) diff --git a/src/parser_h264.c b/src/parser_h264.c index 07bed03b..67a82304 100644 --- a/src/parser_h264.c +++ b/src/parser_h264.c @@ -352,7 +352,7 @@ h264_decode_pic_parameter_set(elementary_stream_t *st, bitstream_t *bs) int h264_decode_slice_header(elementary_stream_t *st, bitstream_t *bs, int *pkttype, - int *duration, int *isfield) + int *isfield) { h264_private_t *p; int slice_type, pps_id, sps_id; @@ -402,22 +402,20 @@ h264_decode_slice_header(elementary_stream_t *st, bitstream_t *bs, int *pkttype, *isfield = field; - 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; - } + int d = 0; + if(p->sps[sps_id].time_scale != 0) + d = timebase * p->sps[sps_id].units_in_tick / p->sps[sps_id].time_scale; if(p->sps[sps_id].cbpsize != 0) st->es_vbv_size = p->sps[sps_id].cbpsize; st->es_vbv_delay = -1; - if(p->sps[sps_id].width && p->sps[sps_id].height && !st->es_buf.sb_err) - parser_set_stream_vsize(st, p->sps[sps_id].width, - p->sps[sps_id].height * - (2 - p->sps[sps_id].mbs_only_flag)); + if(p->sps[sps_id].width && p->sps[sps_id].height && d && !st->es_buf.sb_err) + parser_set_stream_vparam(st, p->sps[sps_id].width, + p->sps[sps_id].height * + (2 - p->sps[sps_id].mbs_only_flag), + d); if(p->sps[sps_id].aspect_num && p->sps[sps_id].aspect_den) { diff --git a/src/parser_h264.h b/src/parser_h264.h index af92a569..5e78b436 100644 --- a/src/parser_h264.h +++ b/src/parser_h264.h @@ -28,6 +28,6 @@ int h264_decode_seq_parameter_set(struct elementary_stream *st, bitstream_t *bs) int h264_decode_pic_parameter_set(struct elementary_stream *st, bitstream_t *bs); int h264_decode_slice_header(struct elementary_stream *st, bitstream_t *bs, - int *pkttype, int *duration, int *isfield); + int *pkttype, int *isfield); #endif /* PARSER_H264_H_ */ diff --git a/src/parsers.c b/src/parsers.c index 9b4768d9..9adc8b20 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -904,16 +904,18 @@ parse_mpeg2video_pic_start(service_t *t, elementary_stream_t *st, int *frametype * */ void -parser_set_stream_vsize(elementary_stream_t *st, int width, int height) +parser_set_stream_vparam(elementary_stream_t *st, int width, int height, + int duration) { int need_save = 0; - if(st->es_width == 0 && st->es_height == 0) { + if(st->es_width == 0 && st->es_height == 0 && st->es_frame_duration == 0) { need_save = 1; st->es_meta_change = 0; - } else if(st->es_width != width || st->es_height != height) { - + } else if(st->es_width != width || st->es_height != height || + st->es_frame_duration != duration) { + st->es_meta_change++; if(st->es_meta_change == 2) need_save = 1; @@ -925,6 +927,7 @@ parser_set_stream_vsize(elementary_stream_t *st, int width, int height) if(need_save) { st->es_width = width; st->es_height = height; + st->es_frame_duration = duration; service_request_save(st->es_service, 1); } } @@ -969,7 +972,7 @@ parse_mpeg2video_seq_start(service_t *t, elementary_stream_t *st, 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)]; + int duration = mpeg2video_framedurations[read_bits(bs, 4)]; v = read_bits(bs, 18) * 400; skip_bits(bs, 1); @@ -977,7 +980,7 @@ parse_mpeg2video_seq_start(service_t *t, elementary_stream_t *st, v = read_bits(bs, 10) * 16 * 1024 / 8; st->es_vbv_size = v; - parser_set_stream_vsize(st, width, height); + parser_set_stream_vparam(st, width, height, duration); return 0; } @@ -1157,8 +1160,7 @@ parse_h264(service_t *t, elementary_stream_t *st, size_t len, { 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; + int l2, pkttype, isfield; bitstream_t bs; int ret = 0; @@ -1169,12 +1171,6 @@ parse_h264(service_t *t, elementary_stream_t *st, size_t len, 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; } @@ -1211,23 +1207,23 @@ parse_h264(service_t *t, elementary_stream_t *st, size_t len, 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)) { + if(h264_decode_slice_header(st, &bs, &pkttype, &isfield)) { free(f); return 1; } free(f); + if(st->es_curpkt != NULL || st->es_frame_duration == 0) + break; + 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_duration = st->es_frame_duration; st->es_curpkt->pkt_commercial = t->s_tt_commercial_advice; break; diff --git a/src/parsers.h b/src/parsers.h index 947b6fd6..826daaed 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -31,7 +31,8 @@ void parse_mpeg_ps(struct service *t, struct elementary_stream *st, void parser_enqueue_packet(struct service *t, struct elementary_stream *st, th_pkt_t *pkt); -void parser_set_stream_vsize(struct elementary_stream *st, int width, int height); +void parser_set_stream_vparam(struct elementary_stream *st, int width, int height, + int duration); extern const unsigned int mpeg2video_framedurations[16]; diff --git a/src/psi.c b/src/psi.c index 9763a50a..ff298fad 100644 --- a/src/psi.c +++ b/src/psi.c @@ -998,6 +998,8 @@ psi_save_service_settings(htsmsg_t *m, service_t *t) htsmsg_add_u32(sub, "width", st->es_width); htsmsg_add_u32(sub, "height", st->es_height); } + if(st->es_frame_duration) + htsmsg_add_u32(sub, "duration", st->es_frame_duration); } htsmsg_add_msg(m, "stream", sub); @@ -1141,6 +1143,9 @@ psi_load_service_settings(htsmsg_t *m, service_t *t) if(!htsmsg_get_u32(c, "height", &u32)) st->es_height = u32; + + if(!htsmsg_get_u32(c, "duration", &u32)) + st->es_frame_duration = u32; } } diff --git a/src/service.c b/src/service.c index 1f8fe565..07805d3e 100644 --- a/src/service.c +++ b/src/service.c @@ -902,6 +902,7 @@ service_build_stream_start(service_t *t) ssc->ssc_pid = st->es_pid; ssc->ssc_width = st->es_width; ssc->ssc_height = st->es_height; + ssc->ssc_frameduration = st->es_frame_duration; } t->s_setsourceinfo(t, &ss->ss_si);