From c15d002917ba51dcdf0addf4fefd544b1bf7f5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 13 Jun 2010 12:18:59 +0000 Subject: [PATCH] Keep track of video width and height and send it over HTSP in subscriptionStart. Fixed ticket #208 --- src/htsp.c | 7 +++++++ src/parser_h264.c | 12 +++++++++--- src/parsers.c | 45 +++++++++++++++++++++++++++++++++++++++++---- src/parsers.h | 2 ++ src/psi.c | 18 +++++++++++++++++- src/streaming.h | 2 ++ src/transports.c | 18 ++++++++++++++---- src/transports.h | 2 +- src/tvhead.h | 4 ++++ 9 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/htsp.c b/src/htsp.c index bcb34829..786ece1d 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -1479,6 +1479,13 @@ htsp_subscription_start(htsp_subscription_t *hs, const streaming_start_t *ss) htsmsg_add_u32(c, "ancillary_id", ssc->ssc_ancillary_id); } + if(ssc->ssc_type == SCT_MPEG2VIDEO || ssc->ssc_type == SCT_H264) { + if(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_msg(streams, NULL, c); } diff --git a/src/parser_h264.c b/src/parser_h264.c index 40580efa..180cc483 100644 --- a/src/parser_h264.c +++ b/src/parser_h264.c @@ -92,6 +92,8 @@ typedef struct h264_private { struct { int frame_duration; int cbpsize; + int16_t width; + int16_t height; } sps[256]; struct { @@ -174,7 +176,7 @@ int h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs) { int profile_idc, level_idc, poc_type; - unsigned int sps_id, tmp, i; + unsigned int sps_id, tmp, i, width, height; int cbpsize = -1; h264_private_t *p; @@ -249,8 +251,11 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs) read_bits1(bs); - tmp = read_golomb_ue(bs) + 1; /* mb width */ - tmp = read_golomb_ue(bs) + 1; /* mb height */ + width = read_golomb_ue(bs) + 1; /* mb width */ + height = read_golomb_ue(bs) + 1; /* mb height */ + + p->sps[sps_id].width = width * 16; + p->sps[sps_id].height = height * 16; if(!read_bits1(bs)) read_bits1(bs); @@ -326,5 +331,6 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype) 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); return 0; } diff --git a/src/parsers.c b/src/parsers.c index 32fc2a96..bbd51087 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -614,6 +614,40 @@ parse_mpeg2video_pic_start(th_transport_t *t, th_stream_t *st, int *frametype, return 0; } +/** + * + */ +void +parser_set_stream_meta(th_stream_t *st, int width, int height, int d) +{ + int need_save = 0; + + if(st->st_frame_duration == 0 && 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) { + + st->st_meta_change++; + if(st->st_meta_change == 2) + need_save = 1; + + } else { + st->st_meta_change = 0; + } + + 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); + } +} + + /** * Parse mpeg2video sequence start */ @@ -621,20 +655,23 @@ static int parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st, bitstream_t *bs) { - int v; + int v, width, height, d; if(bs->len < 61) return 1; - skip_bits(bs, 12); - skip_bits(bs, 12); + width = read_bits(bs, 12); + height = read_bits(bs, 12); skip_bits(bs, 4); - st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)]; + d = 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->st_vbv_size = v; + + parser_set_stream_meta(st, width, height, d); return 0; } diff --git a/src/parsers.h b/src/parsers.h index 9863b0c4..42bca984 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -28,6 +28,8 @@ 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); + extern const unsigned int mpeg2video_framedurations[16]; #endif /* PARSERS_H */ diff --git a/src/psi.c b/src/psi.c index 3055194a..e808d5b1 100644 --- a/src/psi.c +++ b/src/psi.c @@ -672,7 +672,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, update&PMT_UPDATE_CAID_DELETED ? ", CAID deleted":"", update&PMT_REORDERED ? ", PIDs reordered":""); - transport_request_save(t); + transport_request_save(t, 0); // Only restart if something that our clients worry about did change if(update & !(PMT_UPDATE_NEW_CA_STREAM | @@ -977,6 +977,13 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t) 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); + htsmsg_add_u32(sub, "height", st->st_height); + } + } htsmsg_add_msg(m, "stream", sub); } @@ -1116,6 +1123,15 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t) if(!htsmsg_get_u32(c, "parentpid", &u32)) st->st_parent_pid = u32; } + + if(type == SCT_MPEG2VIDEO || type == SCT_H264) { + if(!htsmsg_get_u32(c, "width", &u32)) + st->st_width = u32; + + if(!htsmsg_get_u32(c, "height", &u32)) + st->st_height = u32; + } + } sort_pids(t); } diff --git a/src/streaming.h b/src/streaming.h index d3be0a31..dcabea4b 100644 --- a/src/streaming.h +++ b/src/streaming.h @@ -30,6 +30,8 @@ typedef struct streaming_start_component { char ssc_lang[4]; uint16_t ssc_composition_id; uint16_t ssc_ancillary_id; + int16_t ssc_width; + int16_t ssc_height; } streaming_start_component_t; diff --git a/src/transports.c b/src/transports.c index 057bdf9b..925aebb4 100644 --- a/src/transports.c +++ b/src/transports.c @@ -864,6 +864,8 @@ transport_build_stream_start(th_transport_t *t) memcpy(ssc->ssc_lang, st->st_lang, 4); ssc->ssc_composition_id = st->st_composition_id; ssc->ssc_ancillary_id = st->st_ancillary_id; + ssc->ssc_width = st->st_width; + ssc->ssc_height = st->st_height; } t->tht_setsourceinfo(t, &ss->ss_si); @@ -896,15 +898,17 @@ static struct th_transport_queue pending_save_queue; * */ void -transport_request_save(th_transport_t *t) +transport_request_save(th_transport_t *t, int restart) { pthread_mutex_lock(&pending_save_mutex); if(!t->tht_ps_onqueue) { - t->tht_ps_onqueue = 1; + t->tht_ps_onqueue = 1 + !!restart; TAILQ_INSERT_TAIL(&pending_save_queue, t, tht_ps_link); transport_ref(t); pthread_cond_signal(&pending_save_cond); + } else if(restart) { + t->tht_ps_onqueue = 2; // upgrade to restart too } pthread_mutex_unlock(&pending_save_mutex); @@ -918,7 +922,7 @@ static void * transport_saver(void *aux) { th_transport_t *t; - + int restart; pthread_mutex_lock(&pending_save_mutex); while(1) { @@ -927,6 +931,8 @@ transport_saver(void *aux) pthread_cond_wait(&pending_save_cond, &pending_save_mutex); continue; } + assert(t->tht_ps_onqueue != 0); + restart = t->tht_ps_onqueue == 2; TAILQ_REMOVE(&pending_save_queue, t, tht_ps_link); t->tht_ps_onqueue = 0; @@ -936,7 +942,11 @@ transport_saver(void *aux) if(t->tht_status != TRANSPORT_ZOMBIE) t->tht_config_save(t); - + if(t->tht_status == TRANSPORT_RUNNING && restart) { + pthread_mutex_lock(&t->tht_stream_mutex); + transport_restart(t, 1); + pthread_mutex_unlock(&t->tht_stream_mutex); + } transport_unref(t); pthread_mutex_unlock(&global_lock); diff --git a/src/transports.h b/src/transports.h index 49db5a0e..94f9f669 100644 --- a/src/transports.h +++ b/src/transports.h @@ -75,7 +75,7 @@ void transport_restart(th_transport_t *t, int had_components); void transport_stream_destroy(th_transport_t *t, th_stream_t *st); -void transport_request_save(th_transport_t *t); +void transport_request_save(th_transport_t *t, int restart); void transport_source_info_free(source_info_t *si); diff --git a/src/tvhead.h b/src/tvhead.h index e3086f4f..6bbffcb2 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -422,6 +422,10 @@ typedef struct th_stream { int64_t st_prevdts; int64_t st_nextdts; int st_frame_duration; + int st_width; + int st_height; + + int st_meta_change; /* DTS generator */