Keep track of video width and height and send it over HTSP in subscriptionStart.

Fixed ticket #208
This commit is contained in:
Andreas Öman 2010-06-13 12:18:59 +00:00
parent a974a3fb69
commit c15d002917
9 changed files with 97 additions and 13 deletions

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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 */