Changeset 111119 in webkit


Ignore:
Timestamp:
Mar 17, 2012 4:30:21 AM (12 years ago)
Author:
Philippe Normand
Message:

[GStreamer] run AudioFileReader in a nested loop
https://bugs.webkit.org/show_bug.cgi?id=80823

Reviewed by Martin Robinson.

Use a separate main loop for the file reader, this approach is
much cleaner than polling the default GLib main context.

  • platform/audio/gstreamer/AudioFileReaderGStreamer.cpp:

(AudioFileReader):
(WebCore::enteredMainLoopCallback):
(WebCore):
(WebCore::AudioFileReader::AudioFileReader):
(WebCore::AudioFileReader::handleMessage):
(WebCore::AudioFileReader::start):
(WebCore::AudioFileReader::createBus):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r111118 r111119  
     12012-03-12  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GStreamer] run AudioFileReader in a nested loop
     4        https://bugs.webkit.org/show_bug.cgi?id=80823
     5
     6        Reviewed by Martin Robinson.
     7
     8        Use a separate main loop for the file reader, this approach is
     9        much cleaner than polling the default GLib main context.
     10
     11        * platform/audio/gstreamer/AudioFileReaderGStreamer.cpp:
     12        (AudioFileReader):
     13        (WebCore::enteredMainLoopCallback):
     14        (WebCore):
     15        (WebCore::AudioFileReader::AudioFileReader):
     16        (WebCore::AudioFileReader::handleMessage):
     17        (WebCore::AudioFileReader::start):
     18        (WebCore::AudioFileReader::createBus):
     19
    1202012-02-07  Robert Hogan  <robert@webkit.org>
    221
  • trunk/Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp

    r105626 r111119  
    11/*
    2  *  Copyright (C) 2011 Igalia S.L
     2 *  Copyright (C) 2011, 2012 Igalia S.L
    33 *  Copyright (C) 2011 Zan Dobersek  <zandobersek@gmail.com>
    44 *
     
    2525
    2626#include "AudioBus.h"
    27 #include "GOwnPtr.h"
    28 #include "GRefPtr.h"
    2927#include <gio/gio.h>
    3028#include <gst/app/gstappsink.h>
     
    3432#include <wtf/Noncopyable.h>
    3533#include <wtf/PassOwnPtr.h>
     34#include <wtf/gobject/GOwnPtr.h>
     35#include <wtf/gobject/GRefPtr.h>
    3636
    3737namespace WebCore {
     
    5151    void deinterleavePadsConfigured();
    5252    void plugDeinterleave(GstPad*);
     53    void decodeAudioForBusCreation();
    5354
    5455private:
     
    6364    GstBufferListIterator* m_frontRightBuffersIterator;
    6465    GstElement* m_pipeline;
    65     bool m_eos;
    6666    unsigned m_channelSize;
    67 
    68     gulong m_deinterleavePadAddedSignalHandlerId;
    69     gulong m_deinterleaveNoMorePadSignalHandlerId;
     67    GRefPtr<GstElement> m_decodebin;
     68    GRefPtr<GstElement> m_deInterleave;
     69    GRefPtr<GMainLoop> m_loop;
    7070};
    7171
     
    113113}
    114114
     115gboolean enteredMainLoopCallback(gpointer userData)
     116{
     117    AudioFileReader* reader = reinterpret_cast<AudioFileReader*>(userData);
     118    reader->decodeAudioForBusCreation();
     119    return FALSE;
     120}
     121
    115122AudioFileReader::AudioFileReader(const char* filePath)
    116123    : m_data(0)
    117124    , m_dataSize(0)
    118125    , m_filePath(filePath)
    119     , m_eos(false)
     126    , m_channelSize(0)
    120127{
    121128}
     
    125132    , m_dataSize(dataSize)
    126133    , m_filePath(0)
    127     , m_eos(false)
     134    , m_channelSize(0)
    128135{
    129136}
     
    177184    switch (GST_MESSAGE_TYPE(message)) {
    178185    case GST_MESSAGE_EOS:
    179         m_eos = true;
     186        g_main_loop_quit(m_loop.get());
    180187        break;
    181188    case GST_MESSAGE_WARNING:
     
    242249    GstElement* audioResample = gst_element_factory_make("audioresample", 0);
    243250    GstElement* capsFilter = gst_element_factory_make("capsfilter", 0);
    244     GstElement* deInterleave = gst_element_factory_make("deinterleave", "deinterleave");
    245 
    246     g_object_set(deInterleave, "keep-positions", TRUE, NULL);
    247     m_deinterleavePadAddedSignalHandlerId = g_signal_connect(deInterleave, "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this);
    248     m_deinterleaveNoMorePadSignalHandlerId = g_signal_connect(deInterleave, "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this);
     251    m_deInterleave = gst_element_factory_make("deinterleave", "deinterleave");
     252
     253    g_object_set(m_deInterleave.get(), "keep-positions", TRUE, NULL);
     254    g_signal_connect(m_deInterleave.get(), "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this);
     255    g_signal_connect(m_deInterleave.get(), "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this);
    249256
    250257    GstCaps* caps = getGStreamerAudioCaps(2, m_sampleRate);
     
    252259    gst_caps_unref(caps);
    253260
    254     gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, deInterleave, NULL);
     261    gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, m_deInterleave.get(), NULL);
    255262
    256263    GstPad* sinkPad = gst_element_get_static_pad(audioConvert, "sink");
     
    260267    gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING);
    261268    gst_element_link_pads_full(audioResample, "src", capsFilter, "sink", GST_PAD_LINK_CHECK_NOTHING);
    262     gst_element_link_pads_full(capsFilter, "src", deInterleave, "sink", GST_PAD_LINK_CHECK_NOTHING);
     269    gst_element_link_pads_full(capsFilter, "src", m_deInterleave.get(), "sink", GST_PAD_LINK_CHECK_NOTHING);
    263270
    264271    gst_element_sync_state_with_parent(audioConvert);
    265272    gst_element_sync_state_with_parent(audioResample);
    266273    gst_element_sync_state_with_parent(capsFilter);
    267     gst_element_sync_state_with_parent(deInterleave);
    268 }
    269 
    270 
    271 PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono)
    272 {
    273     m_sampleRate = sampleRate;
    274 
    275     static bool gstInitialized = false;
    276     if (!gstInitialized)
    277         gstInitialized = gst_init_check(0, 0, 0);
    278 
    279     if (!gstInitialized)
    280         return nullptr;
    281 
    282     m_frontLeftBuffers = gst_buffer_list_new();
    283     m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers);
    284     gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator);
    285 
    286     m_frontRightBuffers = gst_buffer_list_new();
    287     m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers);
    288     gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator);
    289 
     274    gst_element_sync_state_with_parent(m_deInterleave.get());
     275}
     276
     277void AudioFileReader::decodeAudioForBusCreation()
     278{
    290279    // Build the pipeline (giostreamsrc | filesrc) ! decodebin2
    291280    // A deinterleave element is added once a src pad becomes available in decodebin.
    292281    m_pipeline = gst_pipeline_new(0);
    293282
    294     GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
    295     gst_bus_add_signal_watch(bus);
    296     gulong busSignalHandlerId = g_signal_connect(bus, "message", G_CALLBACK(messageCallback), this);
     283    GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline)));
     284    gst_bus_add_signal_watch(bus.get());
     285    g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this);
    297286
    298287    GstElement* source;
     
    307296    }
    308297
    309     GstElement* decodebin = gst_element_factory_make("decodebin2", "decodebin");
    310     gulong decodebinPadAddedSignalHandlerId = g_signal_connect(decodebin, "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this);
    311 
    312     gst_bin_add_many(GST_BIN(m_pipeline), source, decodebin, NULL);
    313     gst_element_link_pads_full(source, "src", decodebin, "sink", GST_PAD_LINK_CHECK_NOTHING);
    314 
    315     m_eos = false;
    316     m_channelSize = 0;
     298    m_decodebin = gst_element_factory_make("decodebin2", "decodebin");
     299    g_signal_connect(m_decodebin.get(), "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this);
     300
     301    gst_bin_add_many(GST_BIN(m_pipeline), source, m_decodebin.get(), NULL);
     302    gst_element_link_pads_full(source, "src", m_decodebin.get(), "sink", GST_PAD_LINK_CHECK_NOTHING);
    317303    gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
    318     while (!m_eos)
    319         g_main_context_iteration(0, FALSE);
    320 
    321     g_signal_handler_disconnect(bus, busSignalHandlerId);
    322     gst_object_unref(bus);
    323 
    324     g_signal_handler_disconnect(decodebin, decodebinPadAddedSignalHandlerId);
    325 
    326     if (GstElement* deinterleave = gst_bin_get_by_name(GST_BIN(m_pipeline), "deinterleave")) {
    327         if (g_signal_handler_is_connected(deinterleave, m_deinterleavePadAddedSignalHandlerId))
    328             g_signal_handler_disconnect(deinterleave, m_deinterleavePadAddedSignalHandlerId);
    329         if (g_signal_handler_is_connected(deinterleave, m_deinterleaveNoMorePadSignalHandlerId))
    330             g_signal_handler_disconnect(deinterleave, m_deinterleaveNoMorePadSignalHandlerId);
    331         gst_object_unref(deinterleave);
    332     }
     304}
     305
     306PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono)
     307{
     308    m_sampleRate = sampleRate;
     309
     310    static bool gstInitialized = false;
     311    if (!gstInitialized)
     312        gstInitialized = gst_init_check(0, 0, 0);
     313
     314    if (!gstInitialized)
     315        return nullptr;
     316
     317    m_frontLeftBuffers = gst_buffer_list_new();
     318    m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers);
     319    gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator);
     320
     321    m_frontRightBuffers = gst_buffer_list_new();
     322    m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers);
     323    gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator);
     324
     325    GRefPtr<GMainContext> context = g_main_context_new();
     326    g_main_context_push_thread_default(context.get());
     327    m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE));
     328
     329    // Start the pipeline processing just after the loop is started.
     330    GSource* timeoutSource = g_timeout_source_new(0);
     331    g_source_attach(timeoutSource, context.get());
     332    g_source_set_callback(timeoutSource, reinterpret_cast<GSourceFunc>(enteredMainLoopCallback), this, 0);
     333
     334    g_main_loop_run(m_loop.get());
     335    g_main_context_pop_thread_default(context.get());
     336
     337    GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline)));
     338    g_signal_handlers_disconnect_by_func(bus.get(), reinterpret_cast<gpointer>(messageCallback), this);
     339
     340    g_signal_handlers_disconnect_by_func(m_decodebin.get(), reinterpret_cast<gpointer>(onGStreamerDecodebinPadAddedCallback), this);
     341    g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleavePadAddedCallback), this);
     342    g_signal_handlers_disconnect_by_func(m_deInterleave.get(), reinterpret_cast<gpointer>(onGStreamerDeinterleaveReadyCallback), this);
    333343
    334344    unsigned channels = mixToMono ? 1 : 2;
     
    348358    gst_object_unref(GST_OBJECT(m_pipeline));
    349359
     360    m_decodebin.clear();
     361    m_deInterleave.clear();
    350362    return audioBus.release();
    351363}
  • trunk/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp

    r109005 r111119  
    121121}
    122122
     123template <> GRefPtr<GstBus> adoptGRef(GstBus* ptr)
     124{
     125    ASSERT(!GST_OBJECT_IS_FLOATING(GST_OBJECT(ptr)));
     126    return GRefPtr<GstBus>(ptr, GRefPtrAdopt);
     127}
     128
     129template <> GstBus* refGPtr<GstBus>(GstBus* ptr)
     130{
     131    if (ptr)
     132        webkitGstObjectRefSink(GST_OBJECT(ptr));
     133
     134    return ptr;
     135}
     136
     137template <> void derefGPtr<GstBus>(GstBus* ptr)
     138{
     139    if (ptr)
     140        gst_object_unref(ptr);
     141}
     142
    123143}
    124144#endif // USE(GSTREAMER)
  • trunk/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h

    r102791 r111119  
    2929typedef struct _GstCaps GstCaps;
    3030typedef struct _GstTask GstTask;
     31typedef struct _GstBus GstBus;
    3132
    3233namespace WTF {
     
    5152template<> void derefGPtr<GstTask>(GstTask* ptr);
    5253
     54template<> GRefPtr<GstBus> adoptGRef(GstBus* ptr);
     55template<> GstBus* refGPtr<GstBus>(GstBus* ptr);
     56template<> void derefGPtr<GstBus>(GstBus* ptr);
     57
    5358}
    5459
Note: See TracChangeset for help on using the changeset viewer.