dvbsubenc: Write Display Definition Segment if a non-default width/height is used

Otherwise it can't be rendered by dvbsuboverlay or ffmpeg at least.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3446>
This commit is contained in:
Sebastian Dröge 2022-11-21 19:40:35 +02:00 committed by GStreamer Marge Bot
parent c6af0a39e7
commit 76eb870251
3 changed files with 58 additions and 15 deletions

View 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);

View 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:

View 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);