dvbsubenc: Write Display Definition Segment if a non-default width/height is used
authorSebastian Dröge <sebastian@centricular.com>
Mon, 21 Nov 2022 17:40:35 +0000 (19:40 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 22 Nov 2022 21:04:39 +0000 (21:04 +0000)
Otherwise it can't be rendered by dvbsuboverlay or ffmpeg at least.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3446>

subprojects/gst-plugins-bad/gst/dvbsubenc/gstdvbsubenc-util.c
subprojects/gst-plugins-bad/gst/dvbsubenc/gstdvbsubenc.c
subprojects/gst-plugins-bad/gst/dvbsubenc/gstdvbsubenc.h

index c9a152b..e1e8d04 100644 (file)
@@ -721,9 +721,35 @@ dvbenc_write_region_segment (GstByteWriter * b, int object_version, int page_id,
   gst_byte_writer_set_pos (b, pos);
 }
 
+static void
+dvbenc_write_display_definition_segment (GstByteWriter * b, int object_version,
+    int page_id, guint16 width, guint16 height)
+{
+  guint seg_size_pos, pos;
+
+  gst_byte_writer_put_uint8 (b, DVB_SEGMENT_SYNC_BYTE);
+  gst_byte_writer_put_uint8 (b, DVB_SEGMENT_TYPE_DISPLAY_DEFINITION);
+  gst_byte_writer_put_uint16_be (b, page_id);
+
+  /* Size placeholder */
+  seg_size_pos = gst_byte_writer_get_pos (b);
+  gst_byte_writer_put_uint16_be (b, 0);
+
+  /* version number, display window flag, reserved bits */
+  gst_byte_writer_put_uint8 (b, (object_version << 4) | (0 << 3) | 0x07);
+  gst_byte_writer_put_uint16_be (b, width);
+  gst_byte_writer_put_uint16_be (b, height);
+
+  /* Re-write the size field */
+  pos = gst_byte_writer_get_pos (b);
+  gst_byte_writer_set_pos (b, seg_size_pos);
+  gst_byte_writer_put_uint16_be (b, pos - (seg_size_pos + 2));
+  gst_byte_writer_set_pos (b, pos);
+}
+
 GstBuffer *
-gst_dvbenc_encode (int object_version, int page_id, SubpictureRect * s,
-    guint num_subpictures)
+gst_dvbenc_encode (int object_version, int page_id, int display_version,
+    guint16 width, guint16 height, SubpictureRect * s, guint num_subpictures)
 {
   GstByteWriter b;
   guint seg_size_pos, pos;
@@ -744,6 +770,11 @@ gst_dvbenc_encode (int object_version, int page_id, SubpictureRect * s,
    * 0x20 0x00 prefixed */
   gst_byte_writer_put_uint16_be (&b, 0x2000);
 
+  /* If non-default width/height are used, write a display definiton segment */
+  if (width != 720 || height != 576)
+    dvbenc_write_display_definition_segment (&b, display_version, page_id,
+        width, height);
+
   /* Page Composition Segment */
   gst_byte_writer_put_uint8 (&b, DVB_SEGMENT_SYNC_BYTE);
   gst_byte_writer_put_uint8 (&b, DVB_SEGMENT_TYPE_PAGE_COMPOSITION);
index ab25ae2..ad316f7 100644 (file)
@@ -393,7 +393,9 @@ process_largest_subregion (GstDvbSubEnc * enc, GstVideoFrame * vframe)
     s.x = left;
     s.y = top;
 
-    packet = gst_dvbenc_encode (enc->object_version & 0xF, 1, &s, 1);
+    packet =
+        gst_dvbenc_encode (enc->object_version & 0xF, 1, enc->display_version,
+        enc->in_info.width, enc->in_info.height, &s, 1);
     if (packet == NULL) {
       gst_video_frame_unmap (&ayuv8p_frame);
       goto fail;
@@ -440,7 +442,9 @@ gst_dvb_sub_enc_generate_end_packet (GstDvbSubEnc * enc, GstClockTime pts)
   GST_DEBUG_OBJECT (enc, "Outputting end of page at TS %" GST_TIME_FORMAT,
       GST_TIME_ARGS (enc->current_end_time));
 
-  packet = gst_dvbenc_encode (enc->object_version & 0xF, 1, NULL, 0);
+  packet =
+      gst_dvbenc_encode (enc->object_version & 0xF, 1, enc->display_version,
+      enc->in_info.width, enc->in_info.height, NULL, 0);
   if (packet == NULL) {
     GST_ELEMENT_ERROR (enc, STREAM, FAILED,
         ("Internal data stream error."),
@@ -501,27 +505,34 @@ gst_dvb_sub_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstDvbSubEnc *enc = GST_DVB_SUB_ENC (gst_pad_get_parent (pad));
   gboolean ret = FALSE;
+  GstVideoInfo in_info;
   GstCaps *out_caps = NULL;
 
   GST_DEBUG_OBJECT (enc, "setcaps called with %" GST_PTR_FORMAT, caps);
-  if (!gst_video_info_from_caps (&enc->in_info, caps)) {
+  if (!gst_video_info_from_caps (&in_info, caps)) {
     GST_ERROR_OBJECT (enc, "Failed to parse input caps");
     return FALSE;
   }
 
-  out_caps = gst_caps_new_simple ("subpicture/x-dvb",
-      "width", G_TYPE_INT, enc->in_info.width,
-      "height", G_TYPE_INT, enc->in_info.height,
-      "framerate", GST_TYPE_FRACTION, enc->in_info.fps_n, enc->in_info.fps_d,
-      NULL);
+  if (!enc->in_info.finfo || !gst_video_info_is_equal (&in_info, &enc->in_info)) {
+    enc->in_info = in_info;
+    enc->display_version++;
+
+    out_caps = gst_caps_new_simple ("subpicture/x-dvb",
+        "width", G_TYPE_INT, enc->in_info.width,
+        "height", G_TYPE_INT, enc->in_info.height,
+        "framerate", GST_TYPE_FRACTION, enc->in_info.fps_n, enc->in_info.fps_d,
+        NULL);
+
+    if (!gst_pad_set_caps (enc->srcpad, out_caps)) {
+      GST_WARNING_OBJECT (enc, "failed setting downstream caps");
+      gst_caps_unref (out_caps);
+      goto beach;
+    }
 
-  if (!gst_pad_set_caps (enc->srcpad, out_caps)) {
-    GST_WARNING_OBJECT (enc, "failed setting downstream caps");
     gst_caps_unref (out_caps);
-    goto beach;
   }
 
-  gst_caps_unref (out_caps);
   ret = TRUE;
 
 beach:
index 507e9f5..c43c6b1 100644 (file)
@@ -47,6 +47,7 @@ struct _GstDvbSubEnc
   GstElement element;
 
   GstVideoInfo in_info;
+  int display_version;
   GstPad *sinkpad;
   GstPad *srcpad;
 
@@ -68,4 +69,4 @@ GST_ELEMENT_REGISTER_DECLARE (dvbsubenc);
 
 gboolean gst_dvbsubenc_ayuv_to_ayuv8p (GstVideoFrame * src, GstVideoFrame * dest, int max_colours, guint32 *out_num_colours);
 
-GstBuffer *gst_dvbenc_encode (int object_version, int page_id, SubpictureRect *s, guint num_subpictures);
+GstBuffer *gst_dvbenc_encode (int object_version, int page_id, int display_version, guint16 width, guint16 height, SubpictureRect *s, guint num_subpictures);