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);
}
struct {
int frame_duration;
int cbpsize;
+ int16_t width;
+ int16_t height;
} sps[256];
struct {
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;
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);
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;
}
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
*/
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;
}
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 */
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 |
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);
}
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);
}
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;
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);
*
*/
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);
transport_saver(void *aux)
{
th_transport_t *t;
-
+ int restart;
pthread_mutex_lock(&pending_save_mutex);
while(1) {
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;
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);
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);
int64_t st_prevdts;
int64_t st_nextdts;
int st_frame_duration;
+ int st_width;
+ int st_height;
+
+ int st_meta_change;
/* DTS generator */