Keep track of video width and height and send it over HTSP in subscriptionStart.
Fixed ticket #208
This commit is contained in:
parent
a974a3fb69
commit
c15d002917
9 changed files with 97 additions and 13 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
18
src/psi.c
18
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue