File: GStreamerRTPVideoRotationHeaderExtension.cpp

package info (click to toggle)
webkit2gtk 2.49.90-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 445,664 kB
  • sloc: cpp: 3,797,881; javascript: 197,914; ansic: 161,337; python: 49,141; asm: 21,979; ruby: 18,539; perl: 16,723; xml: 4,623; yacc: 2,360; sh: 2,246; java: 2,019; lex: 1,327; pascal: 366; makefile: 295
file content (129 lines) | stat: -rw-r--r-- 4,794 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 *  Copyright (C) 2025 Igalia S.L. All rights reserved.
 *  Copyright (C) 2025 Metrological Group B.V.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "GStreamerRTPVideoRotationHeaderExtension.h"

#if USE(GSTREAMER_WEBRTC)

#include "VideoFrameMetadataGStreamer.h"
#include <gst/rtp/rtp.h>
#include <wtf/PrintStream.h>
#include <wtf/glib/WTFGType.h>

using namespace WebCore;

typedef struct _RTPVideoRotationHeaderExtensionPrivate {
} RTPVideoRotationHeaderExtensionPrivate;

typedef struct _RTPVideoRotationHeaderExtension {
    GstRTPHeaderExtension parent;
    RTPVideoRotationHeaderExtensionPrivate* priv;
} RTPVideoRotationHeaderExtension;

typedef struct _RTPVideoRotationHeaderExtensionClass {
    GstRTPHeaderExtensionClass parentClass;
} RTPVideoRotationHeaderExtensionClass;

GST_DEBUG_CATEGORY_STATIC(extensionDebug);
#define GST_CAT_DEFAULT extensionDebug

WEBKIT_DEFINE_TYPE_WITH_CODE(RTPVideoRotationHeaderExtension, webkit_gst_rtp_video_rotation_header_extension, GST_TYPE_RTP_HEADER_EXTENSION, GST_DEBUG_CATEGORY_INIT(extensionDebug, "webkitrtpvideorotation", 0, "RTP Video Header Extension"))

static GstRTPHeaderExtensionFlags extensionGetSupportedFlags(GstRTPHeaderExtension*)
{
    return static_cast<GstRTPHeaderExtensionFlags>(GST_RTP_HEADER_EXTENSION_ONE_BYTE | GST_RTP_HEADER_EXTENSION_TWO_BYTE);
}

static gsize extensionGetMaxSize(GstRTPHeaderExtension*, const GstBuffer*)
{
    return 1;
}

static gssize extensionWrite(GstRTPHeaderExtension* extension, const GstBuffer* inputBuffer, GstRTPHeaderExtensionFlags, GstBuffer*, guint8* data, gsize)
{
    auto [rotation, isMirrored] = webkitGstBufferGetVideoRotation(const_cast<GstBuffer*>(inputBuffer));
    gssize written = 1;

    switch (rotation) {
    case VideoFrame::Rotation::None:
        data[0] = 0x0;
        break;
    case VideoFrame::Rotation::Left:
        data[0] = 0x1;
        break;
    case VideoFrame::Rotation::UpsideDown:
        data[0] = 0x2;
        break;
    case VideoFrame::Rotation::Right:
        data[0] = 0x3;
        break;
    }

    if (isMirrored)
        data[0] |= 1 << 3;

    GST_TRACE_OBJECT(extension, "Wrote %" G_GSSIZE_FORMAT " bytes from video rotation %u (flipped: %s) to byte 0x%x", written, static_cast<unsigned>(rotation), WTF::boolForPrinting(isMirrored), data[0]);
    return written;
}

static gboolean extensionRead(GstRTPHeaderExtension* extension, GstRTPHeaderExtensionFlags, const guint8* data, gsize, GstBuffer* buffer)
{
    VideoFrame::Rotation rotation = VideoFrame::Rotation::None;
    uint8_t firstByte = data[0];

    switch (firstByte & 0x7) {
    case 0:
        break;
    case 1:
        rotation = VideoFrame::Rotation::Left;
        break;
    case 2:
        rotation = VideoFrame::Rotation::UpsideDown;
        break;
    case 3:
        rotation = VideoFrame::Rotation::Right;
        break;
    default:
        return FALSE;
    }

    bool isMirrored = (firstByte >> 3) & 0x1;
    GST_TRACE_OBJECT(extension, "Read byte 0x%x to video rotation %u (flipped: %s)", firstByte, static_cast<unsigned>(rotation), boolForPrinting(isMirrored));
    webkitGstBufferAddVideoFrameMetadata(buffer, { }, rotation, isMirrored, VideoFrameContentHint::None);
    return TRUE;
}

static void webkit_gst_rtp_video_rotation_header_extension_class_init(RTPVideoRotationHeaderExtensionClass* klass)
{
    auto rtpHeaderExtensionClass = GST_RTP_HEADER_EXTENSION_CLASS(klass);

    rtpHeaderExtensionClass->get_supported_flags = extensionGetSupportedFlags;
    rtpHeaderExtensionClass->get_max_size = extensionGetMaxSize;
    rtpHeaderExtensionClass->write = extensionWrite;
    rtpHeaderExtensionClass->read = extensionRead;

    gst_element_class_set_static_metadata(GST_ELEMENT_CLASS(klass), "3GPP Orientation RTP Header Extension", GST_RTP_HDREXT_ELEMENT_CLASS,
        "Read/write 3GPP Orientation from/to RTP packets", "Philippe Normand <philn@igalia.com>");
    gst_rtp_header_extension_class_set_uri(rtpHeaderExtensionClass, "urn:3gpp:video-orientation");
}

#undef GST_CAT_DEFAULT

#endif // USE(GSTREAMER_WEBRTC)