]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Keep track of video width and height and send it over HTSP in subscriptionStart.
authorAndreas Öman <andreas@lonelycoder.com>
Sun, 13 Jun 2010 12:18:59 +0000 (12:18 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Sun, 13 Jun 2010 12:18:59 +0000 (12:18 +0000)
Fixed ticket #208

src/htsp.c
src/parser_h264.c
src/parsers.c
src/parsers.h
src/psi.c
src/streaming.h
src/transports.c
src/transports.h
src/tvhead.h

index bcb34829cc976512d12a2240099f7e35b07f4de0..786ece1d3c6ecff6ecab58089dff713b19439706 100644 (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);
   }
   
index 40580efac68a9a88185ae773c64bedbc4ba4a8a9..180cc483754af1f76edd8e22c869e38664a48cb7 100644 (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;
 }
index 32fc2a9661804fa28e84eaa38fbf7dab43e290f2..bbd51087cfc00d82c3ddecdc4631bebcc317c151 100644 (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;
 }
 
index 9863b0c481d46786a6e61f836685c0fa40798aab..42bca984b11b170315407284c328fd0079f05ccb 100644 (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 */
index 3055194ac80bff97b6bb9ba4734dbbfc824ed159..e808d5b1442ef54ee7f39a5011bb68c3a030fee3 100644 (file)
--- 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);
 }
index d3be0a31be7239c39fbfe9ec9400c888f4a84e15..dcabea4b1f1a3298c97f04eeba139c5013abdfdd 100644 (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;
 
 
index 057bdf9b88f3048c2a94f0ad69167f65459ce2da..925aebb43321fbec542cbaf331c65b9500d3c03d 100644 (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);
index 49db5a0e858accc5bc3053c5a8a2d77589fb05a1..94f9f66984302b3d2aea9bcafe7254eb0434306c 100644 (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);
 
index e3086f4ff2c5e06fa35d72d77a3234ebc529a611..6bbffcb22e8b0a6dbee7c8756e13460cd68b2dfe 100644 (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 */