[GStreamer] use FastMalloc-based GstAllocator
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / GStreamerUtilities.cpp
1 /*
2  *  Copyright (C) 2012, 2015, 2016 Igalia S.L
3  *  Copyright (C) 2015, 2016 Metrological Group B.V.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20
21 #include "config.h"
22
23 #if USE(GSTREAMER)
24 #include "GStreamerUtilities.h"
25
26 #include "GRefPtrGStreamer.h"
27 #include "GstAllocatorFastMalloc.h"
28 #include "IntSize.h"
29
30 #include <gst/audio/audio-info.h>
31 #include <gst/gst.h>
32 #include <wtf/glib/GUniquePtr.h>
33
34 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
35 #define GST_USE_UNSTABLE_API
36 #include <gst/mpegts/mpegts.h>
37 #undef GST_USE_UNSTABLE_API
38 #endif
39
40 namespace WebCore {
41
42 const char* webkitGstMapInfoQuarkString = "webkit-gst-map-info";
43
44 GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTemplate, const gchar* name, GstPad* target)
45 {
46     GstPad* pad;
47     GstPadTemplate* padTemplate = gst_static_pad_template_get(staticPadTemplate);
48
49     if (target)
50         pad = gst_ghost_pad_new_from_template(name, target, padTemplate);
51     else
52         pad = gst_ghost_pad_new_no_target_from_template(name, padTemplate);
53
54     gst_object_unref(padTemplate);
55
56     return pad;
57 }
58
59 #if ENABLE(VIDEO)
60 bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride)
61 {
62     GstVideoInfo info;
63
64     gst_video_info_init(&info);
65     if (!gst_video_info_from_caps(&info, caps))
66         return false;
67
68     format = GST_VIDEO_INFO_FORMAT(&info);
69     size.setWidth(GST_VIDEO_INFO_WIDTH(&info));
70     size.setHeight(GST_VIDEO_INFO_HEIGHT(&info));
71     pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
72     pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
73     stride = GST_VIDEO_INFO_PLANE_STRIDE(&info, 0);
74
75     return true;
76 }
77
78 bool getSampleVideoInfo(GstSample* sample, GstVideoInfo& videoInfo)
79 {
80     if (!GST_IS_SAMPLE(sample))
81         return false;
82
83     GstCaps* caps = gst_sample_get_caps(sample);
84     if (!caps)
85         return false;
86
87     gst_video_info_init(&videoInfo);
88     if (!gst_video_info_from_caps(&videoInfo, caps))
89         return false;
90
91     return true;
92 }
93 #endif
94
95 GstBuffer* createGstBuffer(GstBuffer* buffer)
96 {
97     gsize bufferSize = gst_buffer_get_size(buffer);
98     GstBuffer* newBuffer = gst_buffer_new_and_alloc(bufferSize);
99
100     if (!newBuffer)
101         return 0;
102
103     gst_buffer_copy_into(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_METADATA), 0, bufferSize);
104     return newBuffer;
105 }
106
107 GstBuffer* createGstBufferForData(const char* data, int length)
108 {
109     GstBuffer* buffer = gst_buffer_new_and_alloc(length);
110
111     gst_buffer_fill(buffer, 0, data, length);
112
113     return buffer;
114 }
115
116 char* getGstBufferDataPointer(GstBuffer* buffer)
117 {
118     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
119     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_get_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
120     return reinterpret_cast<char*>(mapInfo->data);
121 }
122
123 void mapGstBuffer(GstBuffer* buffer, uint32_t flags)
124 {
125     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(fastMalloc(sizeof(GstMapInfo)));
126     if (!gst_buffer_map(buffer, mapInfo, static_cast<GstMapFlags>(flags))) {
127         fastFree(mapInfo);
128         gst_buffer_unref(buffer);
129         return;
130     }
131
132     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
133     gst_mini_object_set_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString), mapInfo, nullptr);
134 }
135
136 void unmapGstBuffer(GstBuffer* buffer)
137 {
138     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
139     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_steal_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
140
141     if (!mapInfo)
142         return;
143
144     gst_buffer_unmap(buffer, mapInfo);
145     fastFree(mapInfo);
146 }
147
148 bool initializeGStreamer()
149 {
150     if (gst_is_initialized())
151         return true;
152
153     GUniqueOutPtr<GError> error;
154     // FIXME: We should probably pass the arguments from the command line.
155     bool gstInitialized = gst_init_check(nullptr, nullptr, &error.outPtr());
156     ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
157
158     if (isFastMallocEnabled()) {
159         const char* disableFastMalloc = getenv("WEBKIT_GST_DISABLE_FAST_MALLOC");
160         if (!disableFastMalloc || !strcmp(disableFastMalloc, "0"))
161             gst_allocator_set_default(GST_ALLOCATOR(g_object_new(gst_allocator_fast_malloc_get_type(), nullptr)));
162     }
163
164 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
165     if (gstInitialized)
166         gst_mpegts_initialize();
167 #endif
168
169     return gstInitialized;
170 }
171
172 unsigned getGstPlayFlag(const char* nick)
173 {
174     static GFlagsClass* flagsClass = static_cast<GFlagsClass*>(g_type_class_ref(g_type_from_name("GstPlayFlags")));
175     ASSERT(flagsClass);
176
177     GFlagsValue* flag = g_flags_get_value_by_nick(flagsClass, nick);
178     if (!flag)
179         return 0;
180
181     return flag->value;
182 }
183
184 // Convert a MediaTime in seconds to a GstClockTime. Note that we can get MediaTime objects with a time scale that isn't a GST_SECOND, since they can come to
185 // us through the internal testing API, the DOM and internally. It would be nice to assert the format of the incoming time, but all the media APIs assume time
186 // is passed around in fractional seconds, so we'll just have to assume the same.
187 uint64_t toGstUnsigned64Time(const MediaTime& mediaTime)
188 {
189     MediaTime time = mediaTime.toTimeScale(GST_SECOND);
190     if (time.isInvalid())
191         return GST_CLOCK_TIME_NONE;
192     return time.timeValue();
193 }
194
195 bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString)
196 {
197     GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
198     GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false);
199     bool result = candidates;
200
201     gst_plugin_feature_list_free(candidates);
202     return result;
203 }
204
205 }
206
207 #endif // USE(GSTREAMER)