[GStreamer] A video element isn't drawn onto the canvas.
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / GStreamerUtilities.cpp
1 /*
2  *  Copyright (C) 2012 Igalia S.L
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19
20 #include "config.h"
21
22 #if USE(GSTREAMER)
23 #include "GStreamerUtilities.h"
24
25 #include "IntSize.h"
26
27 #include <gst/audio/audio-info.h>
28 #include <gst/gst.h>
29 #include <wtf/MathExtras.h>
30 #include <wtf/glib/GUniquePtr.h>
31
32 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
33 #define GST_USE_UNSTABLE_API
34 #include <gst/mpegts/mpegts.h>
35 #undef GST_USE_UNSTABLE_API
36 #endif
37
38 namespace WebCore {
39
40 const char* webkitGstMapInfoQuarkString = "webkit-gst-map-info";
41
42 GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTemplate, const gchar* name, GstPad* target)
43 {
44     GstPad* pad;
45     GstPadTemplate* padTemplate = gst_static_pad_template_get(staticPadTemplate);
46
47     if (target)
48         pad = gst_ghost_pad_new_from_template(name, target, padTemplate);
49     else
50         pad = gst_ghost_pad_new_no_target_from_template(name, padTemplate);
51
52     gst_object_unref(padTemplate);
53
54     return pad;
55 }
56
57 #if ENABLE(VIDEO)
58 bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride)
59 {
60     GstVideoInfo info;
61
62     gst_video_info_init(&info);
63     if (!gst_video_info_from_caps(&info, caps))
64         return false;
65
66     format = GST_VIDEO_INFO_FORMAT(&info);
67     size.setWidth(GST_VIDEO_INFO_WIDTH(&info));
68     size.setHeight(GST_VIDEO_INFO_HEIGHT(&info));
69     pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
70     pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
71     stride = GST_VIDEO_INFO_PLANE_STRIDE(&info, 0);
72
73     return true;
74 }
75
76 bool getSampleVideoInfo(GstSample* sample, GstVideoInfo& videoInfo)
77 {
78     if (!GST_IS_SAMPLE(sample))
79         return false;
80
81     GstCaps* caps = gst_sample_get_caps(sample);
82     if (!caps)
83         return false;
84
85     gst_video_info_init(&videoInfo);
86     if (!gst_video_info_from_caps(&videoInfo, caps))
87         return false;
88
89     return true;
90 }
91 #endif
92
93 GstBuffer* createGstBuffer(GstBuffer* buffer)
94 {
95     gsize bufferSize = gst_buffer_get_size(buffer);
96     GstBuffer* newBuffer = gst_buffer_new_and_alloc(bufferSize);
97
98     if (!newBuffer)
99         return 0;
100
101     gst_buffer_copy_into(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_METADATA), 0, bufferSize);
102     return newBuffer;
103 }
104
105 GstBuffer* createGstBufferForData(const char* data, int length)
106 {
107     GstBuffer* buffer = gst_buffer_new_and_alloc(length);
108
109     gst_buffer_fill(buffer, 0, data, length);
110
111     return buffer;
112 }
113
114 char* getGstBufferDataPointer(GstBuffer* buffer)
115 {
116     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
117     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_get_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
118     return reinterpret_cast<char*>(mapInfo->data);
119 }
120
121 void mapGstBuffer(GstBuffer* buffer)
122 {
123     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(fastMalloc(sizeof(GstMapInfo)));
124     if (!gst_buffer_map(buffer, mapInfo, GST_MAP_WRITE)) {
125         fastFree(mapInfo);
126         gst_buffer_unref(buffer);
127         return;
128     }
129
130     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
131     gst_mini_object_set_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString), mapInfo, 0);
132 }
133
134 void unmapGstBuffer(GstBuffer* buffer)
135 {
136     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
137     GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_steal_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
138
139     if (!mapInfo)
140         return;
141
142     gst_buffer_unmap(buffer, mapInfo);
143     fastFree(mapInfo);
144 }
145
146 bool initializeGStreamer()
147 {
148     if (gst_is_initialized())
149         return true;
150
151     GUniqueOutPtr<GError> error;
152     // FIXME: We should probably pass the arguments from the command line.
153     bool gstInitialized = gst_init_check(0, 0, &error.outPtr());
154     ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
155
156 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
157     if (gstInitialized)
158         gst_mpegts_initialize();
159 #endif
160
161     return gstInitialized;
162 }
163
164 unsigned getGstPlayFlag(const char* nick)
165 {
166     static GFlagsClass* flagsClass = static_cast<GFlagsClass*>(g_type_class_ref(g_type_from_name("GstPlayFlags")));
167     ASSERT(flagsClass);
168
169     GFlagsValue* flag = g_flags_get_value_by_nick(flagsClass, nick);
170     if (!flag)
171         return 0;
172
173     return flag->value;
174 }
175
176 GstClockTime toGstClockTime(float time)
177 {
178     // Extract the integer part of the time (seconds) and the fractional part (microseconds). Attempt to
179     // round the microseconds so no floating point precision is lost and we can perform an accurate seek.
180     float seconds;
181     float microSeconds = modff(time, &seconds) * 1000000;
182     GTimeVal timeValue;
183     timeValue.tv_sec = static_cast<glong>(seconds);
184     timeValue.tv_usec = static_cast<glong>(roundf(microSeconds / 10000) * 10000);
185     return GST_TIMEVAL_TO_TIME(timeValue);
186 }
187
188 }
189
190 #endif // USE(GSTREAMER)