[GStreamer] Refactor media player to use MediaTime consistently
[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 "IntSize.h"
28
29 #include <gst/audio/audio-info.h>
30 #include <gst/gst.h>
31 #include <wtf/glib/GUniquePtr.h>
32
33 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
34 #define GST_USE_UNSTABLE_API
35 #include <gst/mpegts/mpegts.h>
36 #undef GST_USE_UNSTABLE_API
37 #endif
38
39 namespace WebCore {
40
41 const char* webkitGstMapInfoQuarkString = "webkit-gst-map-info";
42
43 GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTemplate, const gchar* name, GstPad* target)
44 {
45     GstPad* pad;
46     GstPadTemplate* padTemplate = gst_static_pad_template_get(staticPadTemplate);
47
48     if (target)
49         pad = gst_ghost_pad_new_from_template(name, target, padTemplate);
50     else
51         pad = gst_ghost_pad_new_no_target_from_template(name, padTemplate);
52
53     gst_object_unref(padTemplate);
54
55     return pad;
56 }
57
58 #if ENABLE(VIDEO)
59 bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride)
60 {
61     GstVideoInfo info;
62
63     gst_video_info_init(&info);
64     if (!gst_video_info_from_caps(&info, caps))
65         return false;
66
67     format = GST_VIDEO_INFO_FORMAT(&info);
68     size.setWidth(GST_VIDEO_INFO_WIDTH(&info));
69     size.setHeight(GST_VIDEO_INFO_HEIGHT(&info));
70     pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
71     pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
72     stride = GST_VIDEO_INFO_PLANE_STRIDE(&info, 0);
73
74     return true;
75 }
76
77 bool getSampleVideoInfo(GstSample* sample, GstVideoInfo& videoInfo)
78 {
79     if (!GST_IS_SAMPLE(sample))
80         return false;
81
82     GstCaps* caps = gst_sample_get_caps(sample);
83     if (!caps)
84         return false;
85
86     gst_video_info_init(&videoInfo);
87     if (!gst_video_info_from_caps(&videoInfo, caps))
88         return false;
89
90     return true;
91 }
92 #endif
93
94 GstBuffer* createGstBuffer(GstBuffer* buffer)
95 {
96     gsize bufferSize = gst_buffer_get_size(buffer);
97     GstBuffer* newBuffer = gst_buffer_new_and_alloc(bufferSize);
98
99     if (!newBuffer)
100         return 0;
101
102     gst_buffer_copy_into(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_METADATA), 0, bufferSize);
103     return newBuffer;
104 }
105
106 GstBuffer* createGstBufferForData(const char* data, int length)
107 {
108     GstBuffer* buffer = gst_buffer_new_and_alloc(length);
109
110     gst_buffer_fill(buffer, 0, data, length);
111
112     return buffer;
113 }
114
115 char* getGstBufferDataPointer(GstBuffer* buffer)
116 {
117     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
118     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_get_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
119     return reinterpret_cast<char*>(mapInfo->data);
120 }
121
122 void mapGstBuffer(GstBuffer* buffer, uint32_t flags)
123 {
124     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(fastMalloc(sizeof(GstMapInfo)));
125     if (!gst_buffer_map(buffer, mapInfo, static_cast<GstMapFlags>(flags))) {
126         fastFree(mapInfo);
127         gst_buffer_unref(buffer);
128         return;
129     }
130
131     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
132     gst_mini_object_set_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString), mapInfo, nullptr);
133 }
134
135 void unmapGstBuffer(GstBuffer* buffer)
136 {
137     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
138     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_steal_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
139
140     if (!mapInfo)
141         return;
142
143     gst_buffer_unmap(buffer, mapInfo);
144     fastFree(mapInfo);
145 }
146
147 bool initializeGStreamer()
148 {
149     if (gst_is_initialized())
150         return true;
151
152     GUniqueOutPtr<GError> error;
153     // FIXME: We should probably pass the arguments from the command line.
154     bool gstInitialized = gst_init_check(nullptr, nullptr, &error.outPtr());
155     ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
156
157 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
158     if (gstInitialized)
159         gst_mpegts_initialize();
160 #endif
161
162     return gstInitialized;
163 }
164
165 unsigned getGstPlayFlag(const char* nick)
166 {
167     static GFlagsClass* flagsClass = static_cast<GFlagsClass*>(g_type_class_ref(g_type_from_name("GstPlayFlags")));
168     ASSERT(flagsClass);
169
170     GFlagsValue* flag = g_flags_get_value_by_nick(flagsClass, nick);
171     if (!flag)
172         return 0;
173
174     return flag->value;
175 }
176
177 // 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
178 // 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
179 // is passed around in fractional seconds, so we'll just have to assume the same.
180 uint64_t toGstUnsigned64Time(const MediaTime& mediaTime)
181 {
182     MediaTime time = mediaTime.toTimeScale(GST_SECOND);
183     if (time.isInvalid())
184         return GST_CLOCK_TIME_NONE;
185     return time.timeValue();
186 }
187
188 bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString)
189 {
190     GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
191     GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false);
192     bool result = candidates;
193
194     gst_plugin_feature_list_free(candidates);
195     return result;
196 }
197
198 }
199
200 #endif // USE(GSTREAMER)