Changeset 192511 in webkit
- Timestamp:
- Nov 17, 2015, 1:57:42 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
platform/audio/gstreamer/AudioFileReaderGStreamer.cpp (modified) (16 diffs)
-
platform/graphics/gstreamer/GRefPtrGStreamer.cpp (modified) (1 diff)
-
platform/graphics/gstreamer/GRefPtrGStreamer.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r192503 r192511 1 2015-11-17 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GStreamer] Use RunLoop instead of GMainLoop in AudioFileReaderGStreamer 4 https://bugs.webkit.org/show_bug.cgi?id=151256 5 6 Reviewed by Žan Doberšek. 7 8 Use RunLoop instead of the platform specific code. The AudioBus 9 can be created from any thread, so we create a helper thread to 10 ensure we don't use the main RunLoop. 11 12 This patch also includes some code cleanups: 13 - Uses smart pointers when possible. 14 - Fixes uninitialized members in constructors. 15 - Makes private members private. 16 - Uses lambdas instead of static non-members functions. 17 - nullptr instead of 0 in some places. 18 19 * platform/audio/gstreamer/AudioFileReaderGStreamer.cpp: 20 (WebCore::AudioFileReader::createWeakPtr): 21 (WebCore::AudioFileReader::deinterleavePadAddedCallback): 22 (WebCore::AudioFileReader::deinterleaveReadyCallback): 23 (WebCore::AudioFileReader::decodebinPadAddedCallback): 24 (WebCore::AudioFileReader::AudioFileReader): 25 (WebCore::AudioFileReader::~AudioFileReader): 26 (WebCore::AudioFileReader::handleSample): 27 (WebCore::AudioFileReader::handleMessage): 28 (WebCore::AudioFileReader::handleNewDeinterleavePad): 29 (WebCore::AudioFileReader::deinterleavePadsConfigured): 30 (WebCore::AudioFileReader::plugDeinterleave): 31 (WebCore::AudioFileReader::decodeAudioForBusCreation): 32 (WebCore::AudioFileReader::createBus): 33 (WebCore::createBusFromAudioFile): 34 (WebCore::createBusFromInMemoryAudioFile): 35 (WebCore::onAppsinkPullRequiredCallback): Deleted. 36 (WebCore::messageCallback): Deleted. 37 (WebCore::onGStreamerDeinterleavePadAddedCallback): Deleted. 38 (WebCore::onGStreamerDeinterleaveReadyCallback): Deleted. 39 (WebCore::onGStreamerDecodebinPadAddedCallback): Deleted. 40 * platform/graphics/gstreamer/GRefPtrGStreamer.cpp: 41 (WTF::adoptGRef): 42 (WTF::refGPtr<GstBufferList>): 43 (WTF::derefGPtr<GstBufferList>): 44 * platform/graphics/gstreamer/GRefPtrGStreamer.h: 45 1 46 2015-11-16 Eric Carlson <eric.carlson@apple.com> 2 47 -
trunk/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp
r190562 r192511 23 23 24 24 #include "AudioFileReader.h" 25 26 25 #include "AudioBus.h" 27 26 #include "GRefPtrGStreamer.h" 28 27 #include <gio/gio.h> 29 28 #include <gst/app/gstappsink.h> 30 29 #include <gst/audio/audio-info.h> 31 30 #include <gst/gst.h> 31 #include <wtf/MainThread.h> 32 32 #include <wtf/Noncopyable.h> 33 #include <wtf/RunLoop.h> 34 #include <wtf/Threading.h> 35 #include <wtf/WeakPtr.h> 33 36 #include <wtf/glib/GRefPtr.h> 34 #include <wtf/glib/GThreadSafeMainLoopSource.h>35 37 #include <wtf/glib/GUniquePtr.h> 36 38 … … 46 48 PassRefPtr<AudioBus> createBus(float sampleRate, bool mixToMono); 47 49 48 GstFlowReturn handleSample(GstAppSink*); 49 gboolean handleMessage(GstMessage*); 50 private: 51 WeakPtr<AudioFileReader> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); } 52 53 static void deinterleavePadAddedCallback(AudioFileReader*, GstPad*); 54 static void deinterleaveReadyCallback(AudioFileReader*); 55 static void decodebinPadAddedCallback(AudioFileReader*, GstPad*); 56 57 void handleMessage(GstMessage*); 50 58 void handleNewDeinterleavePad(GstPad*); 51 59 void deinterleavePadsConfigured(); 52 60 void plugDeinterleave(GstPad*); 53 61 void decodeAudioForBusCreation(); 54 55 private: 56 const void* m_data; 57 size_t m_dataSize; 58 const char* m_filePath; 59 60 float m_sampleRate; 61 int m_channels; 62 GstBufferList* m_frontLeftBuffers; 63 GstBufferList* m_frontRightBuffers; 64 65 GstElement* m_pipeline; 66 unsigned m_channelSize; 62 GstFlowReturn handleSample(GstAppSink*); 63 64 WeakPtrFactory<AudioFileReader> m_weakPtrFactory; 65 RunLoop& m_runLoop; 66 const void* m_data { nullptr }; 67 size_t m_dataSize { 0 }; 68 const char* m_filePath { nullptr }; 69 70 float m_sampleRate { 0 }; 71 int m_channels { 0 }; 72 GRefPtr<GstBufferList> m_frontLeftBuffers; 73 GRefPtr<GstBufferList> m_frontRightBuffers; 74 75 GRefPtr<GstElement> m_pipeline; 76 unsigned m_channelSize { 0 }; 67 77 GRefPtr<GstElement> m_decodebin; 68 78 GRefPtr<GstElement> m_deInterleave; 69 GRefPtr<GMainLoop> m_loop; 70 bool m_errorOccurred; 79 bool m_errorOccurred { false }; 71 80 }; 72 81 … … 84 93 } 85 94 86 static GstFlowReturn onAppsinkPullRequiredCallback(GstAppSink* sink, gpointer userData) 87 { 88 return static_cast<AudioFileReader*>(userData)->handleSample(sink); 89 } 90 91 gboolean messageCallback(GstBus*, GstMessage* message, AudioFileReader* reader) 92 { 93 return reader->handleMessage(message); 94 } 95 96 static void onGStreamerDeinterleavePadAddedCallback(GstElement*, GstPad* pad, AudioFileReader* reader) 95 void AudioFileReader::deinterleavePadAddedCallback(AudioFileReader* reader, GstPad* pad) 97 96 { 98 97 reader->handleNewDeinterleavePad(pad); 99 98 } 100 99 101 static void onGStreamerDeinterleaveReadyCallback(GstElement*,AudioFileReader* reader)100 void AudioFileReader::deinterleaveReadyCallback(AudioFileReader* reader) 102 101 { 103 102 reader->deinterleavePadsConfigured(); 104 103 } 105 104 106 static void onGStreamerDecodebinPadAddedCallback(GstElement*, GstPad* pad, AudioFileReader* reader)105 void AudioFileReader::decodebinPadAddedCallback(AudioFileReader* reader, GstPad* pad) 107 106 { 108 107 reader->plugDeinterleave(pad); … … 110 109 111 110 AudioFileReader::AudioFileReader(const char* filePath) 112 : m_ data(0)113 , m_ dataSize(0)111 : m_weakPtrFactory(this) 112 , m_runLoop(RunLoop::current()) 114 113 , m_filePath(filePath) 115 , m_channelSize(0)116 , m_errorOccurred(false)117 114 { 118 115 } 119 116 120 117 AudioFileReader::AudioFileReader(const void* data, size_t dataSize) 121 : m_data(data) 118 : m_weakPtrFactory(this) 119 , m_runLoop(RunLoop::current()) 120 , m_data(data) 122 121 , m_dataSize(dataSize) 123 , m_filePath(0)124 , m_channelSize(0)125 , m_errorOccurred(false)126 122 { 127 123 } … … 130 126 { 131 127 if (m_pipeline) { 132 GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline )));128 GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get()))); 133 129 ASSERT(bus); 134 g _signal_handlers_disconnect_by_func(bus.get(), reinterpret_cast<gpointer>(messageCallback), this);135 136 gst_element_set_state(m_pipeline , GST_STATE_NULL);137 gst_object_unref(GST_OBJECT(m_pipeline));130 gst_bus_set_sync_handler(bus.get(), nullptr, nullptr, nullptr); 131 132 gst_element_set_state(m_pipeline.get(), GST_STATE_NULL); 133 m_pipeline = nullptr; 138 134 } 139 135 140 136 if (m_decodebin) { 141 g_signal_handlers_disconnect_ by_func(m_decodebin.get(), reinterpret_cast<gpointer>(onGStreamerDecodebinPadAddedCallback), this);142 m_decodebin .clear();137 g_signal_handlers_disconnect_matched(m_decodebin.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); 138 m_decodebin = nullptr; 143 139 } 144 140 145 141 if (m_deInterleave) { 146 g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleavePadAddedCallback), this); 147 g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleaveReadyCallback), this); 148 m_deInterleave.clear(); 149 } 150 151 gst_buffer_list_unref(m_frontLeftBuffers); 152 gst_buffer_list_unref(m_frontRightBuffers); 142 g_signal_handlers_disconnect_matched(m_deInterleave.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); 143 m_deInterleave = nullptr; 144 } 153 145 } 154 146 155 147 GstFlowReturn AudioFileReader::handleSample(GstAppSink* sink) 156 148 { 157 G stSample* sample = gst_app_sink_pull_sample(sink);149 GRefPtr<GstSample> sample = adoptGRef(gst_app_sink_pull_sample(sink)); 158 150 if (!sample) 159 151 return GST_FLOW_ERROR; 160 152 161 GstBuffer* buffer = gst_sample_get_buffer(sample); 162 if (!buffer) { 163 gst_sample_unref(sample); 153 GstBuffer* buffer = gst_sample_get_buffer(sample.get()); 154 if (!buffer) 164 155 return GST_FLOW_ERROR; 165 } 166 167 GstCaps* caps = gst_sample_get_caps(sample); 168 if (!caps) { 169 gst_sample_unref(sample); 156 157 GstCaps* caps = gst_sample_get_caps(sample.get()); 158 if (!caps) 170 159 return GST_FLOW_ERROR; 171 }172 160 173 161 GstAudioInfo info; … … 180 168 case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: 181 169 case GST_AUDIO_CHANNEL_POSITION_MONO: 182 gst_buffer_list_add(m_frontLeftBuffers , gst_buffer_ref(buffer));170 gst_buffer_list_add(m_frontLeftBuffers.get(), gst_buffer_ref(buffer)); 183 171 m_channelSize += frames; 184 172 break; 185 173 case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: 186 gst_buffer_list_add(m_frontRightBuffers , gst_buffer_ref(buffer));174 gst_buffer_list_add(m_frontRightBuffers.get(), gst_buffer_ref(buffer)); 187 175 break; 188 176 default: … … 190 178 } 191 179 192 gst_sample_unref(sample);193 180 return GST_FLOW_OK; 194 181 } 195 182 196 gboolean AudioFileReader::handleMessage(GstMessage* message) 197 { 183 void AudioFileReader::handleMessage(GstMessage* message) 184 { 185 ASSERT(&m_runLoop == &RunLoop::current()); 186 198 187 GUniqueOutPtr<GError> error; 199 188 GUniqueOutPtr<gchar> debug; … … 201 190 switch (GST_MESSAGE_TYPE(message)) { 202 191 case GST_MESSAGE_EOS: 203 g_main_loop_quit(m_loop.get());192 m_runLoop.stop(); 204 193 break; 205 194 case GST_MESSAGE_WARNING: … … 211 200 g_warning("Error: %d, %s. Debug output: %s", error->code, error->message, debug.get()); 212 201 m_errorOccurred = true; 213 gst_element_set_state(m_pipeline , GST_STATE_NULL);214 g_main_loop_quit(m_loop.get());202 gst_element_set_state(m_pipeline.get(), GST_STATE_NULL); 203 m_runLoop.stop(); 215 204 break; 216 205 default: 217 206 break; 218 207 } 219 return TRUE;220 208 } 221 209 … … 229 217 GstElement* sink = gst_element_factory_make("appsink", 0); 230 218 231 GstAppSinkCallbacks callbacks; 232 callbacks.eos = 0; 233 callbacks.new_preroll = 0; 234 callbacks.new_sample = onAppsinkPullRequiredCallback; 219 static GstAppSinkCallbacks callbacks = { 220 nullptr, // eos 221 nullptr, // new_preroll 222 // new_sample 223 [](GstAppSink* sink, gpointer userData) -> GstFlowReturn { 224 return static_cast<AudioFileReader*>(userData)->handleSample(sink); 225 }, 226 { nullptr } 227 }; 235 228 gst_app_sink_set_callbacks(GST_APP_SINK(sink), &callbacks, this, 0); 236 229 237 230 g_object_set(sink, "sync", FALSE, NULL); 238 231 239 gst_bin_add_many(GST_BIN(m_pipeline), queue, sink, NULL); 240 241 GstPad* sinkPad = gst_element_get_static_pad(queue, "sink"); 242 gst_pad_link_full(pad, sinkPad, GST_PAD_LINK_CHECK_NOTHING); 243 gst_object_unref(GST_OBJECT(sinkPad)); 232 gst_bin_add_many(GST_BIN(m_pipeline.get()), queue, sink, nullptr); 233 234 GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(queue, "sink")); 235 gst_pad_link_full(pad, sinkPad.get(), GST_PAD_LINK_CHECK_NOTHING); 244 236 245 237 gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING); … … 253 245 // All deinterleave src pads are now available, let's roll to 254 246 // PLAYING so data flows towards the sinks and it can be retrieved. 255 gst_element_set_state(m_pipeline , GST_STATE_PLAYING);247 gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING); 256 248 } 257 249 … … 271 263 272 264 g_object_set(m_deInterleave.get(), "keep-positions", TRUE, NULL); 273 g_signal_connect (m_deInterleave.get(), "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this);274 g_signal_connect (m_deInterleave.get(), "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this);275 276 G stCaps* caps =gst_caps_new_simple("audio/x-raw",265 g_signal_connect_swapped(m_deInterleave.get(), "pad-added", G_CALLBACK(deinterleavePadAddedCallback), this); 266 g_signal_connect_swapped(m_deInterleave.get(), "no-more-pads", G_CALLBACK(deinterleaveReadyCallback), this); 267 268 GRefPtr<GstCaps> caps = adoptGRef(gst_caps_new_simple("audio/x-raw", 277 269 "rate", G_TYPE_INT, static_cast<int>(m_sampleRate), 278 270 "channels", G_TYPE_INT, m_channels, 279 271 "format", G_TYPE_STRING, GST_AUDIO_NE(F32), 280 "layout", G_TYPE_STRING, "interleaved", nullptr); 281 g_object_set(capsFilter, "caps", caps, NULL); 282 gst_caps_unref(caps); 283 284 gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, m_deInterleave.get(), NULL); 285 286 GstPad* sinkPad = gst_element_get_static_pad(audioConvert, "sink"); 287 gst_pad_link_full(pad, sinkPad, GST_PAD_LINK_CHECK_NOTHING); 288 gst_object_unref(GST_OBJECT(sinkPad)); 272 "layout", G_TYPE_STRING, "interleaved", nullptr)); 273 g_object_set(capsFilter, "caps", caps.get(), nullptr); 274 275 gst_bin_add_many(GST_BIN(m_pipeline.get()), audioConvert, audioResample, capsFilter, m_deInterleave.get(), nullptr); 276 277 GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(audioConvert, "sink")); 278 gst_pad_link_full(pad, sinkPad.get(), GST_PAD_LINK_CHECK_NOTHING); 289 279 290 280 gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING); … … 300 290 void AudioFileReader::decodeAudioForBusCreation() 301 291 { 292 ASSERT(&m_runLoop == &RunLoop::current()); 293 302 294 // Build the pipeline (giostreamsrc | filesrc) ! decodebin2 303 295 // A deinterleave element is added once a src pad becomes available in decodebin. 304 m_pipeline = gst_pipeline_new( 0);305 306 GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline )));296 m_pipeline = gst_pipeline_new(nullptr); 297 298 GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get()))); 307 299 ASSERT(bus); 308 gst_bus_add_signal_watch(bus.get()); 309 g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this); 300 gst_bus_set_sync_handler(bus.get(), [](GstBus*, GstMessage* message, gpointer userData) { 301 auto& reader = *static_cast<AudioFileReader*>(userData); 302 if (&reader.m_runLoop == &RunLoop::current()) 303 reader.handleMessage(message); 304 else { 305 GRefPtr<GstMessage> protectMessage(message); 306 auto weakThis = reader.createWeakPtr(); 307 reader.m_runLoop.dispatch([weakThis, protectMessage] { 308 if (weakThis) 309 weakThis->handleMessage(protectMessage.get()); 310 }); 311 } 312 gst_message_unref(message); 313 return GST_BUS_DROP; 314 }, this, nullptr); 310 315 311 316 GstElement* source; … … 321 326 322 327 m_decodebin = gst_element_factory_make("decodebin", "decodebin"); 323 g_signal_connect (m_decodebin.get(), "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this);324 325 gst_bin_add_many(GST_BIN(m_pipeline ), source, m_decodebin.get(), NULL);328 g_signal_connect_swapped(m_decodebin.get(), "pad-added", G_CALLBACK(decodebinPadAddedCallback), this); 329 330 gst_bin_add_many(GST_BIN(m_pipeline.get()), source, m_decodebin.get(), NULL); 326 331 gst_element_link_pads_full(source, "src", m_decodebin.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); 327 332 328 // Catch errors here immediately, there might not be an error message if 329 // we're unlucky. 330 if (gst_element_set_state(m_pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { 333 // Catch errors here immediately, there might not be an error message if we're unlucky. 334 if (gst_element_set_state(m_pipeline.get(), GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { 331 335 g_warning("Error: Failed to set pipeline to PAUSED"); 332 336 m_errorOccurred = true; 333 g_main_loop_quit(m_loop.get());337 m_runLoop.stop(); 334 338 } 335 339 } … … 340 344 m_channels = mixToMono ? 1 : 2; 341 345 342 m_frontLeftBuffers = gst_buffer_list_new(); 343 m_frontRightBuffers = gst_buffer_list_new(); 344 345 GRefPtr<GMainContext> context = adoptGRef(g_main_context_new()); 346 g_main_context_push_thread_default(context.get()); 347 m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE)); 346 m_frontLeftBuffers = adoptGRef(gst_buffer_list_new()); 347 m_frontRightBuffers = adoptGRef(gst_buffer_list_new()); 348 348 349 349 // Start the pipeline processing just after the loop is started. 350 GThreadSafeMainLoopSource source; 351 source.schedule("[WebKit] AudioFileReader::decodeAudioForBusCreation", [this] { decodeAudioForBusCreation(); }, G_PRIORITY_DEFAULT, nullptr, context.get()); 352 353 g_main_loop_run(m_loop.get()); 354 g_main_context_pop_thread_default(context.get()); 350 m_runLoop.dispatch([this] { decodeAudioForBusCreation(); }); 351 m_runLoop.run(); 355 352 356 353 // Set pipeline to GST_STATE_NULL state here already ASAP to 357 354 // release any resources that might still be used. 358 gst_element_set_state(m_pipeline , GST_STATE_NULL);355 gst_element_set_state(m_pipeline.get(), GST_STATE_NULL); 359 356 360 357 if (m_errorOccurred) 361 return 0;358 return nullptr; 362 359 363 360 RefPtr<AudioBus> audioBus = AudioBus::create(m_channels, m_channelSize, true); 364 361 audioBus->setSampleRate(m_sampleRate); 365 362 366 copyGstreamerBuffersToAudioChannel(m_frontLeftBuffers , audioBus->channel(0));363 copyGstreamerBuffersToAudioChannel(m_frontLeftBuffers.get(), audioBus->channel(0)); 367 364 if (!mixToMono) 368 copyGstreamerBuffersToAudioChannel(m_frontRightBuffers , audioBus->channel(1));365 copyGstreamerBuffersToAudioChannel(m_frontRightBuffers.get(), audioBus->channel(1)); 369 366 370 367 return audioBus; … … 373 370 PassRefPtr<AudioBus> createBusFromAudioFile(const char* filePath, bool mixToMono, float sampleRate) 374 371 { 375 return AudioFileReader(filePath).createBus(sampleRate, mixToMono); 372 RefPtr<AudioBus> returnValue; 373 auto threadID = createThread("AudioFileReader", [&returnValue, filePath, mixToMono, sampleRate] { 374 returnValue = AudioFileReader(filePath).createBus(sampleRate, mixToMono); 375 }); 376 waitForThreadCompletion(threadID); 377 return returnValue; 376 378 } 377 379 378 380 PassRefPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, float sampleRate) 379 381 { 380 return AudioFileReader(data, dataSize).createBus(sampleRate, mixToMono); 382 RefPtr<AudioBus> returnValue; 383 auto threadID = createThread("AudioFileReader", [&returnValue, data, dataSize, mixToMono, sampleRate] { 384 returnValue = AudioFileReader(data, dataSize).createBus(sampleRate, mixToMono); 385 }); 386 waitForThreadCompletion(threadID); 387 return returnValue; 381 388 } 382 389 -
trunk/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp
r191948 r192511 184 184 } 185 185 186 template<> GRefPtr<GstBufferList> adoptGRef(GstBufferList* ptr) 187 { 188 return GRefPtr<GstBufferList>(ptr, GRefPtrAdopt); 189 } 190 191 template<> GstBufferList* refGPtr<GstBufferList>(GstBufferList* ptr) 192 { 193 if (ptr) 194 gst_buffer_list_ref(ptr); 195 196 return ptr; 197 } 198 199 template<> void derefGPtr<GstBufferList>(GstBufferList* ptr) 200 { 201 if (ptr) 202 gst_buffer_list_unref(ptr); 203 } 204 186 205 template<> GRefPtr<GstSample> adoptGRef(GstSample* ptr) 187 206 { -
trunk/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h
r191948 r192511 32 32 typedef struct _GstElementFactory GstElementFactory; 33 33 typedef struct _GstBuffer GstBuffer; 34 typedef struct _GstBufferList GstBufferList; 34 35 typedef struct _GstSample GstSample; 35 36 typedef struct _GstTagList GstTagList; … … 74 75 template<> void derefGPtr<GstBuffer>(GstBuffer* ptr); 75 76 77 template<> GRefPtr<GstBufferList> adoptGRef(GstBufferList*); 78 template<> GstBufferList* refGPtr<GstBufferList>(GstBufferList*); 79 template<> void derefGPtr<GstBufferList>(GstBufferList*); 80 76 81 template<> GRefPtr<GstSample> adoptGRef(GstSample* ptr); 77 82 template<> GstSample* refGPtr<GstSample>(GstSample* ptr);
Note:
See TracChangeset
for help on using the changeset viewer.