]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Write aspect ratio in recorded MKV files
authorAndreas Öman <andreas@lonelycoder.com>
Wed, 1 Sep 2010 16:28:13 +0000 (16:28 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Wed, 1 Sep 2010 16:28:13 +0000 (16:28 +0000)
src/dvr/mkmux.c
src/packet.h
src/parser_h264.c
src/parsers.c
src/plumbing/globalheaders.c
src/streaming.h
src/tvhead.h

index d6a71c40e524cc95aadf4028d3a75e2ed329ccf5..cbb003fd2771d703b11007918eb9d3f0018e8c4a 100644 (file)
@@ -269,6 +269,13 @@ mk_build_tracks(mk_mux_t *mkm, const struct streaming_start *ss)
       ebml_append_uint(vi, 0xb0, ssc->ssc_width);
       ebml_append_uint(vi, 0xba, ssc->ssc_height);
 
+      if(ssc->ssc_aspect_num && ssc->ssc_aspect_den) {
+       ebml_append_uint(vi, 0x54b2, 3); // Display width/height is in DAR
+       ebml_append_uint(vi, 0x54b0, ssc->ssc_aspect_num);
+       ebml_append_uint(vi, 0x54ba, ssc->ssc_aspect_den);
+
+      }
+
       ebml_append_master(t, 0xe0, vi);
     }
 
index 0398c11221dd884773273bc63e3abed84e5b4aec..0ed40ad59d749ff279be0d34391a9f6c31e92bab 100644 (file)
@@ -50,6 +50,9 @@ typedef struct th_pkt {
   uint8_t pkt_channels;
   uint8_t pkt_sri;
 
+  uint16_t pkt_aspect_num;
+  uint16_t pkt_aspect_den;
+
   pktbuf_t *pkt_payload;
   pktbuf_t *pkt_header;
 
index 71e6d775c3dc6ad8ecf0c6a14f035efd89cad603..19bc3757a3188cd438783b82d29e31b6640a30ff 100644 (file)
@@ -99,6 +99,8 @@ typedef struct h264_private {
     char fixed_rate;
     int units_in_tick;
     int time_scale;
+    uint16_t aspect_num;
+    uint16_t aspect_den;
   } sps[256];
   
   struct {
@@ -109,14 +111,44 @@ typedef struct h264_private {
 
 
 
+static const uint16_t h264_aspect[17][2] = {
+ {0, 1},
+ {1, 1},
+ {12, 11},
+ {10, 11},
+ {16, 11},
+ {40, 33},
+ {24, 11},
+ {20, 11},
+ {32, 11},
+ {80, 33},
+ {18, 11},
+ {15, 11},
+ {64, 33},
+ {160,99},
+ {4, 3},
+ {3, 2},
+ {2, 1},
+};
+
 
 static int 
 decode_vui(h264_private_t *p, bitstream_t *bs, int sps_id)
 {
+  p->sps[sps_id].aspect_num = 0;
+  p->sps[sps_id].aspect_den = 1;
+
   if(read_bits1(bs)) {
-    if(read_bits(bs, 8) == 255) {
-      read_bits(bs, 16);
-      read_bits(bs, 16);
+    int aspect = read_bits(bs, 8);
+
+    if(aspect == 255) {
+      uint16_t num = read_bits(bs, 16);
+      uint16_t den = read_bits(bs, 16);
+      p->sps[sps_id].aspect_num = num;
+      p->sps[sps_id].aspect_den = den;
+    } else if(aspect < 17) {
+      p->sps[sps_id].aspect_num =  h264_aspect[aspect][0];
+      p->sps[sps_id].aspect_den =  h264_aspect[aspect][1];
     }
   }
 
@@ -357,5 +389,9 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype,
     parser_set_stream_vsize(st, p->sps[sps_id].width, 
                            p->sps[sps_id].height *
                            (2 - p->sps[sps_id].mbs_only_flag));
+
+  st->st_aspect_num = p->sps[sps_id].aspect_num;
+  st->st_aspect_den = p->sps[sps_id].aspect_den;
+
   return 0;
 }
index 5ae0c38f04ec81e99d068efec68527acac1651e3..124941f20123bf59eff0a894422d5b3f1ba8e91f 100644 (file)
@@ -757,6 +757,26 @@ parser_set_stream_vsize(th_stream_t *st, int width, int height)
 }
 
 
+static const uint8_t mpeg2_aspect[16][2]={
+    {0,1},
+    {1,1},
+    {4,3},
+    {16,9},
+    {221,100},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+    {0,1},
+};
+
+
 /**
  * Parse mpeg2video sequence start
  */
@@ -764,14 +784,18 @@ static int
 parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st,
                           bitstream_t *bs)
 {
-  int v, width, height;
+  int v, width, height, aspect;
 
   if(bs->len < 61)
     return 1;
   
   width = read_bits(bs, 12);
   height = read_bits(bs, 12);
-  skip_bits(bs, 4);
+  aspect = read_bits(bs, 4);
+
+  st->st_aspect_num = mpeg2_aspect[aspect][0];
+  st->st_aspect_den = mpeg2_aspect[aspect][1];
+
   st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)];
 
   v = read_bits(bs, 18) * 400;
@@ -1143,6 +1167,9 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
         pktbuf_len(pkt->pkt_payload));
 #endif
 
+  pkt->pkt_aspect_num = st->st_aspect_num;
+  pkt->pkt_aspect_den = st->st_aspect_den;
+
   //  avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
 
   /**
index c35f8d8d396b5e5893f2ab58a2aa9e985c49b655..d99c56c43d7ea9c9a0bae09a48b06f0db9f9a222 100644 (file)
@@ -67,6 +67,13 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt)
     ssc->ssc_sri      = pkt->pkt_sri;
   }
 
+  if(SCT_ISVIDEO(ssc->ssc_type)) {
+    if(pkt->pkt_aspect_num && pkt->pkt_aspect_den) {
+      ssc->ssc_aspect_num = pkt->pkt_aspect_num;
+      ssc->ssc_aspect_den = pkt->pkt_aspect_den;
+    }
+  }
+
   if(ssc->ssc_gh != NULL)
     return;
 
@@ -82,6 +89,7 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt)
 
   case SCT_H264:
   case SCT_MPEG2VIDEO:
+
     if(pkt->pkt_header != NULL) {
       ssc->ssc_gh = pkt->pkt_header;
       pktbuf_ref_inc(ssc->ssc_gh);
@@ -95,12 +103,17 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt)
  *
  */
 static int
-header_complete(streaming_start_component_t *ssc)
+header_complete(streaming_start_component_t *ssc, int not_so_picky)
 {
   if((SCT_ISAUDIO(ssc->ssc_type) || SCT_ISVIDEO(ssc->ssc_type)) &&
      ssc->ssc_frameduration == 0)
     return 0;
 
+  if(SCT_ISVIDEO(ssc->ssc_type)) {
+    if(!not_so_picky && (ssc->ssc_aspect_num == 0 || ssc->ssc_aspect_den == 0))
+      return 0;
+  }
+
   if(SCT_ISAUDIO(ssc->ssc_type) &&
      (ssc->ssc_sri == 0 || ssc->ssc_channels == 0))
     return 0;
@@ -121,16 +134,16 @@ headers_complete(globalheaders_t *gh, int64_t qd)
 {
   streaming_start_t *ss = gh->gh_ss;
   streaming_start_component_t *ssc;
-  int i;
+  int i, threshold = qd > (MAX_SCAN_TIME * 90);
 
   assert(ss != NULL);
  
   for(i = 0; i < ss->ss_num_components; i++) {
     ssc = &ss->ss_components[i];
 
-    if(!header_complete(ssc)) {
+    if(!header_complete(ssc, threshold)) {
 
-      if(qd > (MAX_SCAN_TIME * 90)) {
+      if(threshold) {
        ssc->ssc_disabled = 1;
       } else {
        return 0;
index ac878e17242b1248dd1f61148981a17a5f4c7d8a..48b0c865ed0fa99b4ca0c230c1b345689b82dab6 100644 (file)
@@ -33,10 +33,12 @@ typedef struct streaming_start_component {
   uint16_t ssc_pid;
   int16_t ssc_width;
   int16_t ssc_height;
+  int16_t ssc_aspect_num;
+  int16_t ssc_aspect_den;
   uint8_t ssc_sri;
   uint8_t ssc_channels;
   uint8_t ssc_disabled;
-
+  
   pktbuf_t *ssc_gh;
 
   int ssc_frameduration;
index f208936a26559914b978019a51245e231e5ba230..e374d38985b4ae838f66ebbe69210bc5ac5e47f4 100644 (file)
@@ -380,6 +380,9 @@ typedef struct th_stream {
   streaming_component_type_t st_type;
   int st_index;
 
+  uint16_t st_aspect_num;
+  uint16_t st_aspect_den;
+
   char st_lang[4];           /* ISO 639 3-letter language code */
   uint16_t st_composition_id;
   uint16_t st_ancillary_id;