matroskamux: Implement rotation tag support

Similar to qtmux, but for mkv and webm containers.

Tested against other Gst elements and MPV. Note that the later
apparently does not show correct results for flipped values.
In particular the Yaw value seems to get ignored by many clients.

Can be tested with:

```
gst-launch-1.0 \
videotestsrc num-buffers=90 ! \
taginject tags="image-orientation=rotate-270" ! \
capsfilter caps=video/x-raw,width=640,height=480,max-framerate=30/1 ! \
videoconvert ! \
queue ! \
vp8enc ! \
queue ! \
webmmux ! \
filesink location=./test.webm
```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8319>
This commit is contained in:
Robert Mader 2025-01-20 00:37:58 +01:00 committed by GStreamer Marge Bot
parent b2702b6f10
commit a7c2899990

View File

@ -2693,9 +2693,81 @@ gst_matroska_mux_write_colour (GstMatroskaMux * mux,
}
static void
gst_matroska_mux_track_header (GstMatroskaMux * mux,
GstMatroskaTrackContext * context)
gst_matroska_mux_write_projection (GstMatroskaMux * mux,
GstMatroskaMuxPad * pad)
{
GstEbmlWrite *ebml = mux->ebml_write;
gchar *orientation;
guint64 master;
float yaw, roll;
if (!pad->tags ||
!gst_tag_list_get_string (pad->tags, GST_TAG_IMAGE_ORIENTATION,
&orientation)) {
const GstTagList *global_tags;
global_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
if (!global_tags ||
!gst_tag_list_get_string (global_tags, GST_TAG_IMAGE_ORIENTATION,
&orientation))
return;
}
if (!g_strcmp0 ("rotate-0", orientation)) {
yaw = 0.0;
roll = 0.0;
} else if (!g_strcmp0 ("rotate-90", orientation)) {
yaw = 0.0;
roll = -90.0;
} else if (!g_strcmp0 ("rotate-180", orientation)) {
yaw = 0.0;
roll = 180.0;
} else if (!g_strcmp0 ("rotate-270", orientation)) {
yaw = 0.0;
roll = 90.0;
} else if (!g_strcmp0 ("flip-rotate-0", orientation)) {
yaw = 180.0;
roll = 0.0;
} else if (!g_strcmp0 ("flip-rotate-90", orientation)) {
yaw = 180.0;
roll = -90.0;
} else if (!g_strcmp0 ("flip-rotate-180", orientation)) {
yaw = 180.0;
roll = 180.0;
} else if (!g_strcmp0 ("flip-rotate-270", orientation)) {
yaw = 180.0;
roll = 90.0;
} else {
GST_FIXME_OBJECT (mux, "Unsupported orientation %s", orientation);
yaw = 0.0;
roll = 0.0;
}
/* Default projection, skip writing */
if (yaw == 0.0 && roll == 0.0) {
g_free (orientation);
return;
}
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_VIDEOPROJECTION);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPROJECTIONTYPE, 0);
gst_ebml_write_float (ebml, GST_MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, yaw);
gst_ebml_write_float (ebml, GST_MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, 0.0);
gst_ebml_write_float (ebml, GST_MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, roll);
gst_ebml_write_master_finish (ebml, master);
GST_INFO_OBJECT (mux,
"Wrote projection type: 0 yaw: %f pitch: 0.0 row: %f from tag: %s", yaw,
roll, orientation);
g_free (orientation);
}
static void
gst_matroska_mux_track_header (GstMatroskaMux * mux, GstMatroskaMuxPad * pad)
{
GstMatroskaTrackContext *context = pad->track;
GstEbmlWrite *ebml = mux->ebml_write;
guint64 master;
@ -2757,7 +2829,10 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
(gpointer) & fcc_le, 4);
}
gst_matroska_mux_write_colour (mux, videocontext);
gst_matroska_mux_write_projection (mux, pad);
if (videocontext->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
guint64 stereo_mode = 0;
@ -3236,7 +3311,7 @@ gst_matroska_mux_start_file (GstMatroskaMux * mux)
pad->track->num = tracknum++;
child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
gst_matroska_mux_track_header (mux, pad->track);
gst_matroska_mux_track_header (mux, pad);
gst_ebml_write_master_finish (ebml, child);
/* some remaining pad/track setup */
pad->default_duration_scaled =