⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 175928 in webkit


Ignore:
Timestamp:
Nov 11, 2014, 8:13:22 AM (12 years ago)
Author:
Carlos Garcia Campos
Message:

Merge r175370 - [GStreamer] Video resolution changes trigger a crash in the TextureMapper
https://bugs.webkit.org/show_bug.cgi?id=137065

Reviewed by Gustavo Noronha Silva.

Switch to GstSample for buffer+caps communication between the
video sink and the player. Using a single object type for this
avoid issues where the caps might not correctly describe the
buffer contents anymore, for example when the video resolution is
changed.

  • platform/graphics/gstreamer/ImageGStreamer.h: Use GstSample

instead of GstBuffer+GstCaps.
(WebCore::ImageGStreamer::createImage):

  • platform/graphics/gstreamer/ImageGStreamerCairo.cpp: Ditto.

(ImageGStreamer::ImageGStreamer):

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:

(WebCore::mediaPlayerPrivateRepaintCallback): The repaint signal
now uses a GstSample instead of a GstBuffer.
(WebCore::MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase):
Store the current sample instead of a buffer. Also renamed the
mutex protecting access to the sample.
(WebCore::MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase): Ditto.
(WebCore::MediaPlayerPrivateGStreamerBase::naturalSize): Return
early if no sample is available. The caps used to get the video
size are store in the sample.
(WebCore::MediaPlayerPrivateGStreamerBase::updateTexture): Use
GstSample instead of GstBuffer.
(WebCore::MediaPlayerPrivateGStreamerBase::triggerRepaint): Ditto.
(WebCore::MediaPlayerPrivateGStreamerBase::paint): Ditto.

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
  • platform/graphics/gstreamer/VideoSinkGStreamer.cpp: Now store a

GstSample internally. Also removed the now useless current-caps property.
(_WebKitVideoSinkPrivate::_WebKitVideoSinkPrivate): Renamed the
mutex protecting access to the sample.
(_WebKitVideoSinkPrivate::~_WebKitVideoSinkPrivate): Ditto.
(webkit_video_sink_init): Disable last-sample in basesink since we
already store one in our sink anyway.
(webkitVideoSinkTimeoutCallback): Switch to GstSample.
(webkitVideoSinkRender): Ditto.
(unlockSampleMutex): Ditto.
(webkitVideoSinkUnlock): Ditto.
(webkitVideoSinkUnlockStop): Ditto.
(webkitVideoSinkStop): Ditto!
(webkitVideoSinkStart): Ditto.
(webkit_video_sink_class_init): Drop current-caps property.
(webkitVideoSinkGetProperty): Deleted.
(unlockBufferMutex): Deleted.

Location:
releases/WebKitGTK/webkit-2.6/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/ChangeLog

    r175926 r175928  
     12014-10-24  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GStreamer] Video resolution changes trigger a crash in the TextureMapper
     4        https://bugs.webkit.org/show_bug.cgi?id=137065
     5
     6        Reviewed by Gustavo Noronha Silva.
     7
     8        Switch to GstSample for buffer+caps communication between the
     9        video sink and the player. Using a single object type for this
     10        avoid issues where the caps might not correctly describe the
     11        buffer contents anymore, for example when the video resolution is
     12        changed.
     13
     14        * platform/graphics/gstreamer/ImageGStreamer.h: Use GstSample
     15        instead of GstBuffer+GstCaps.
     16        (WebCore::ImageGStreamer::createImage):
     17        * platform/graphics/gstreamer/ImageGStreamerCairo.cpp: Ditto.
     18        (ImageGStreamer::ImageGStreamer):
     19        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
     20        (WebCore::mediaPlayerPrivateRepaintCallback): The repaint signal
     21        now uses a GstSample instead of a GstBuffer.
     22        (WebCore::MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase):
     23        Store the current sample instead of a buffer. Also renamed the
     24        mutex protecting access to the sample.
     25        (WebCore::MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase): Ditto.
     26        (WebCore::MediaPlayerPrivateGStreamerBase::naturalSize): Return
     27        early if no sample is available. The caps used to get the video
     28        size are store in the sample.
     29        (WebCore::MediaPlayerPrivateGStreamerBase::updateTexture): Use
     30        GstSample instead of GstBuffer.
     31        (WebCore::MediaPlayerPrivateGStreamerBase::triggerRepaint): Ditto.
     32        (WebCore::MediaPlayerPrivateGStreamerBase::paint): Ditto.
     33        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
     34        * platform/graphics/gstreamer/VideoSinkGStreamer.cpp: Now store a
     35        GstSample internally. Also removed the now useless current-caps property.
     36        (_WebKitVideoSinkPrivate::_WebKitVideoSinkPrivate): Renamed the
     37        mutex protecting access to the sample.
     38        (_WebKitVideoSinkPrivate::~_WebKitVideoSinkPrivate): Ditto.
     39        (webkit_video_sink_init): Disable last-sample in basesink since we
     40        already store one in our sink anyway.
     41        (webkitVideoSinkTimeoutCallback): Switch to GstSample.
     42        (webkitVideoSinkRender): Ditto.
     43        (unlockSampleMutex): Ditto.
     44        (webkitVideoSinkUnlock): Ditto.
     45        (webkitVideoSinkUnlockStop): Ditto.
     46        (webkitVideoSinkStop): Ditto!
     47        (webkitVideoSinkStart): Ditto.
     48        (webkit_video_sink_class_init): Drop current-caps property.
     49        (webkitVideoSinkGetProperty): Deleted.
     50        (unlockBufferMutex): Deleted.
     51
    1522014-10-29  Said Abou-Hallawa  <sabouhallawa@apple.com>
    253
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h

    r168060 r175928  
    3939class ImageGStreamer : public RefCounted<ImageGStreamer> {
    4040    public:
    41         static PassRefPtr<ImageGStreamer> createImage(GstBuffer* buffer, GstCaps* caps)
     41        static PassRefPtr<ImageGStreamer> createImage(GstSample* sample)
    4242        {
    43             return adoptRef(new ImageGStreamer(buffer, caps));
     43            return adoptRef(new ImageGStreamer(sample));
    4444        }
    4545        ~ImageGStreamer();
     
    6161
    6262    private:
    63         ImageGStreamer(GstBuffer*, GstCaps*);
     63        ImageGStreamer(GstSample*);
    6464        RefPtr<BitmapImage> m_image;
    6565        FloatRect m_cropRect;
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp

    r168060 r175928  
    3333using namespace WebCore;
    3434
    35 ImageGStreamer::ImageGStreamer(GstBuffer* buffer, GstCaps* caps)
     35ImageGStreamer::ImageGStreamer(GstSample* sample)
    3636{
     37    GstCaps* caps = gst_sample_get_caps(sample);
    3738    GstVideoInfo videoInfo;
    3839    gst_video_info_init(&videoInfo);
     
    4344    ASSERT(GST_VIDEO_INFO_N_PLANES(&videoInfo) == 1);
    4445
     46    GstBuffer* buffer = gst_sample_get_buffer(sample);
    4547    if (!gst_video_frame_map(&m_videoFrame, &videoInfo, buffer, GST_MAP_READ))
    4648        return;
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp

    r174638 r175928  
    8080}
    8181
    82 static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamerBase* playerPrivate)
    83 {
    84     playerPrivate->triggerRepaint(buffer);
     82static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstSample* sample, MediaPlayerPrivateGStreamerBase* playerPrivate)
     83{
     84    playerPrivate->triggerRepaint(sample);
    8585}
    8686
     
    9090    , m_readyState(MediaPlayer::HaveNothing)
    9191    , m_networkState(MediaPlayer::Empty)
    92     , m_buffer(0)
     92    , m_sample(0)
    9393    , m_repaintHandler(0)
    9494    , m_volumeSignalHandler(0)
    9595    , m_muteSignalHandler(0)
    9696{
    97     g_mutex_init(&m_bufferMutex);
     97    g_mutex_init(&m_sampleMutex);
    9898}
    9999
     
    105105    }
    106106
    107     g_mutex_clear(&m_bufferMutex);
    108 
    109     if (m_buffer)
    110         gst_buffer_unref(m_buffer);
    111     m_buffer = 0;
     107    g_mutex_clear(&m_sampleMutex);
     108
     109    if (m_sample)
     110        gst_sample_unref(m_sample);
     111    m_sample = 0;
    112112
    113113    m_player = 0;
     
    138138        return m_videoSize;
    139139
    140     GRefPtr<GstCaps> caps = currentVideoSinkCaps();
     140    GMutexLocker<GMutex> lock(m_sampleMutex);
     141    if (!m_sample)
     142        return IntSize();
     143
     144    GstCaps* caps = gst_sample_get_caps(m_sample);
    141145    if (!caps)
    142146        return IntSize();
     
    153157    IntSize originalSize;
    154158    GstVideoFormat format;
    155     if (!getVideoSizeAndFormatFromCaps(caps.get(), originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride))
     159    if (!getVideoSizeAndFormatFromCaps(caps, originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride))
    156160        return IntSize();
    157161
     
    276280PassRefPtr<BitmapTexture> MediaPlayerPrivateGStreamerBase::updateTexture(TextureMapper* textureMapper)
    277281{
    278     GMutexLocker<GMutex> lock(m_bufferMutex);
    279     if (!m_buffer)
     282    GMutexLocker<GMutex> lock(m_sampleMutex);
     283    if (!m_sample)
    280284        return nullptr;
    281285
    282     GRefPtr<GstCaps> caps = currentVideoSinkCaps();
     286    GstCaps* caps = gst_sample_get_caps(m_sample);
    283287    if (!caps)
    284288        return nullptr;
     
    286290    GstVideoInfo videoInfo;
    287291    gst_video_info_init(&videoInfo);
    288     if (!gst_video_info_from_caps(&videoInfo, caps.get()))
     292    if (!gst_video_info_from_caps(&videoInfo, caps))
    289293        return nullptr;
    290294
    291295    IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));
    292296    RefPtr<BitmapTexture> texture = textureMapper->acquireTextureFromPool(size, GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? BitmapTexture::SupportsAlpha : BitmapTexture::NoFlag);
     297    GstBuffer* buffer = gst_sample_get_buffer(m_sample);
    293298
    294299#if GST_CHECK_VERSION(1, 1, 0)
    295300    GstVideoGLTextureUploadMeta* meta;
    296     if ((meta = gst_buffer_get_video_gl_texture_upload_meta(m_buffer))) {
     301    if ((meta = gst_buffer_get_video_gl_texture_upload_meta(buffer))) {
    297302        if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture.
    298303            const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(texture.get());
     
    309314
    310315    GstVideoFrame videoFrame;
    311     if (!gst_video_frame_map(&videoFrame, &videoInfo, m_buffer, GST_MAP_READ))
     316    if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, GST_MAP_READ))
    312317        return nullptr;
    313318
     
    321326#endif
    322327
    323 void MediaPlayerPrivateGStreamerBase::triggerRepaint(GstBuffer* buffer)
    324 {
    325     g_return_if_fail(GST_IS_BUFFER(buffer));
     328void MediaPlayerPrivateGStreamerBase::triggerRepaint(GstSample* sample)
     329{
     330    g_return_if_fail(GST_IS_SAMPLE(sample));
    326331
    327332    {
    328         GMutexLocker<GMutex> lock(m_bufferMutex);
    329         gst_buffer_replace(&m_buffer, buffer);
     333        GMutexLocker<GMutex> lock(m_sampleMutex);
     334        if (m_sample)
     335            gst_sample_unref(m_sample);
     336        m_sample = gst_sample_ref(sample);
    330337    }
    331338
     
    358365        return;
    359366
    360     GMutexLocker<GMutex> lock(m_bufferMutex);
    361     if (!m_buffer)
    362         return;
    363 
    364     GRefPtr<GstCaps> caps = currentVideoSinkCaps();
    365     if (!caps)
    366         return;
    367 
    368     RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer, caps.get());
     367    GMutexLocker<GMutex> lock(m_sampleMutex);
     368    if (!m_sample)
     369        return;
     370
     371    RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_sample);
    369372    if (!gstImage)
    370373        return;
     
    408411
    409412    return MediaPlayer::Download;
    410 }
    411 
    412 GRefPtr<GstCaps> MediaPlayerPrivateGStreamerBase::currentVideoSinkCaps() const
    413 {
    414     if (!m_webkitVideoSink)
    415         return nullptr;
    416 
    417     GRefPtr<GstCaps> currentCaps;
    418     g_object_get(G_OBJECT(m_webkitVideoSink.get()), "current-caps", &currentCaps.outPtr(), NULL);
    419     return currentCaps;
    420413}
    421414
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h

    r174638 r175928  
    3737#endif
    3838
    39 typedef struct _GstBuffer GstBuffer;
     39typedef struct _GstSample GstSample;
    4040typedef struct _GstElement GstElement;
    4141typedef struct _GstMessage GstMessage;
     
    7878    void sizeChanged();
    7979
    80     void triggerRepaint(GstBuffer*);
     80    void triggerRepaint(GstSample*);
    8181    void paint(GraphicsContext*, const IntRect&);
    8282
     
    111111    MediaPlayerPrivateGStreamerBase(MediaPlayer*);
    112112    virtual GstElement* createVideoSink();
    113     GRefPtr<GstCaps> currentVideoSinkCaps() const;
    114113
    115114    void setStreamVolumeElement(GstStreamVolume*);
     
    124123    MediaPlayer::NetworkState m_networkState;
    125124    IntSize m_size;
    126     GMutex m_bufferMutex;
    127     GstBuffer* m_buffer;
     125    mutable GMutex m_sampleMutex;
     126    GstSample* m_sample;
    128127    GThreadSafeMainLoopSource m_volumeTimerHandler;
    129128    GThreadSafeMainLoopSource m_muteTimerHandler;
  • releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp

    r174638 r175928  
    6767};
    6868
    69 enum {
    70     PROP_0,
    71     PROP_CAPS
    72 };
    73 
    7469static guint webkitVideoSinkSignals[LAST_SIGNAL] = { 0, };
    7570
     
    7772    _WebKitVideoSinkPrivate()
    7873    {
    79         g_mutex_init(&bufferMutex);
     74        g_mutex_init(&sampleMutex);
    8075        g_cond_init(&dataCondition);
    8176        gst_video_info_init(&info);
     
    8479    ~_WebKitVideoSinkPrivate()
    8580    {
    86         g_mutex_clear(&bufferMutex);
     81        g_mutex_clear(&sampleMutex);
    8782        g_cond_clear(&dataCondition);
    8883    }
    8984
    90     GstBuffer* buffer;
     85    GstSample* sample;
    9186    GThreadSafeMainLoopSource timeoutSource;
    92     GMutex bufferMutex;
     87    GMutex sampleMutex;
    9388    GCond dataCondition;
    9489
     
    10499    // to deadlocks because render() holds the stream lock.
    105100    //
    106     // Protected by the buffer mutex
     101    // Protected by the sample mutex
    107102    bool unlocked;
    108103};
     
    115110{
    116111    sink->priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
     112    g_object_set(GST_BASE_SINK(sink), "enable-last-sample", FALSE, NULL);
    117113    new (sink->priv) WebKitVideoSinkPrivate();
    118114}
     
    122118    WebKitVideoSinkPrivate* priv = sink->priv;
    123119
    124     GMutexLocker<GMutex> lock(priv->bufferMutex);
    125     GstBuffer* buffer = priv->buffer;
    126     priv->buffer = 0;
    127 
    128     if (!buffer || priv->unlocked || UNLIKELY(!GST_IS_BUFFER(buffer))) {
     120    GMutexLocker<GMutex> lock(priv->sampleMutex);
     121    GstSample* sample = priv->sample;
     122    priv->sample = 0;
     123
     124    if (!sample || priv->unlocked || UNLIKELY(!GST_IS_SAMPLE(sample))) {
    129125        g_cond_signal(&priv->dataCondition);
    130126        return;
    131127    }
    132128
    133     g_signal_emit(sink, webkitVideoSinkSignals[REPAINT_REQUESTED], 0, buffer);
    134     gst_buffer_unref(buffer);
     129    g_signal_emit(sink, webkitVideoSinkSignals[REPAINT_REQUESTED], 0, sample);
     130    gst_sample_unref(sample);
    135131    g_cond_signal(&priv->dataCondition);
    136132}
     
    141137    WebKitVideoSinkPrivate* priv = sink->priv;
    142138
    143     GMutexLocker<GMutex> lock(priv->bufferMutex);
     139    GMutexLocker<GMutex> lock(priv->sampleMutex);
    144140
    145141    if (priv->unlocked)
    146142        return GST_FLOW_OK;
    147143
    148     priv->buffer = gst_buffer_ref(buffer);
     144    priv->sample = gst_sample_new(buffer, priv->currentCaps, 0, 0);
    149145
    150146    // The video info structure is valid only if the sink handled an allocation query.
    151147    GstVideoFormat format = GST_VIDEO_INFO_FORMAT(&priv->info);
    152148    if (format == GST_VIDEO_FORMAT_UNKNOWN) {
    153         gst_buffer_unref(buffer);
     149        gst_sample_unref(priv->sample);
    154150        return GST_FLOW_ERROR;
    155151    }
     
    180176
    181177        if (!gst_video_frame_map(&sourceFrame, &priv->info, buffer, GST_MAP_READ)) {
    182             gst_buffer_unref(buffer);
     178            gst_sample_unref(priv->sample);
    183179            gst_buffer_unref(newBuffer);
    184180            return GST_FLOW_ERROR;
     
    186182        if (!gst_video_frame_map(&destinationFrame, &priv->info, newBuffer, GST_MAP_WRITE)) {
    187183            gst_video_frame_unmap(&sourceFrame);
    188             gst_buffer_unref(buffer);
    189184            gst_buffer_unref(newBuffer);
    190185            return GST_FLOW_ERROR;
     
    216211        gst_video_frame_unmap(&sourceFrame);
    217212        gst_video_frame_unmap(&destinationFrame);
    218         gst_buffer_unref(buffer);
    219         buffer = priv->buffer = newBuffer;
     213        gst_sample_unref(priv->sample);
     214        priv->sample = gst_sample_new(newBuffer, priv->currentCaps, 0, 0);
    220215    }
    221216#endif
     
    228223        [sink] { gst_object_unref(sink); });
    229224
    230     g_cond_wait(&priv->dataCondition, &priv->bufferMutex);
     225    g_cond_wait(&priv->dataCondition, &priv->sampleMutex);
    231226    return GST_FLOW_OK;
    232227}
     
    238233}
    239234
    240 static void webkitVideoSinkGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* parameterSpec)
    241 {
    242     WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
    243     WebKitVideoSinkPrivate* priv = sink->priv;
    244 
    245     switch (propertyId) {
    246     case PROP_CAPS: {
    247         GstCaps* caps = priv->currentCaps;
    248         if (caps)
    249             gst_caps_ref(caps);
    250         g_value_take_boxed(value, caps);
    251         break;
    252     }
    253     default:
    254         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, parameterSpec);
    255     }
    256 }
    257 
    258 static void unlockBufferMutex(WebKitVideoSinkPrivate* priv)
    259 {
    260     GMutexLocker<GMutex> lock(priv->bufferMutex);
    261 
    262     if (priv->buffer) {
    263         gst_buffer_unref(priv->buffer);
    264         priv->buffer = 0;
     235static void unlockSampleMutex(WebKitVideoSinkPrivate* priv)
     236{
     237    GMutexLocker<GMutex> lock(priv->sampleMutex);
     238
     239    if (priv->sample) {
     240        gst_sample_unref(priv->sample);
     241        priv->sample = 0;
    265242    }
    266243
     
    274251    WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink);
    275252
    276     unlockBufferMutex(sink->priv);
     253    unlockSampleMutex(sink->priv);
    277254
    278255    return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock, (baseSink), TRUE);
     
    284261
    285262    {
    286         GMutexLocker<GMutex> lock(priv->bufferMutex);
     263        GMutexLocker<GMutex> lock(priv->sampleMutex);
    287264        priv->unlocked = false;
    288265    }
     
    295272    WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(baseSink)->priv;
    296273
    297     unlockBufferMutex(priv);
     274    unlockSampleMutex(priv);
    298275
    299276    if (priv->currentCaps) {
     
    309286    WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(baseSink)->priv;
    310287
    311     GMutexLocker<GMutex> lock(priv->bufferMutex);
     288    GMutexLocker<GMutex> lock(priv->sampleMutex);
    312289    priv->unlocked = false;
    313290    return TRUE;
     
    364341
    365342    gobjectClass->finalize = webkitVideoSinkFinalize;
    366     gobjectClass->get_property = webkitVideoSinkGetProperty;
    367343
    368344    baseSinkClass->unlock = webkitVideoSinkUnlock;
     
    374350    baseSinkClass->set_caps = webkitVideoSinkSetCaps;
    375351    baseSinkClass->propose_allocation = webkitVideoSinkProposeAllocation;
    376 
    377     g_object_class_install_property(gobjectClass, PROP_CAPS,
    378         g_param_spec_boxed("current-caps", "Current-Caps", "Current caps", GST_TYPE_CAPS, G_PARAM_READABLE));
    379352
    380353    webkitVideoSinkSignals[REPAINT_REQUESTED] = g_signal_new("repaint-requested",
     
    387360            G_TYPE_NONE, // Return type
    388361            1, // Only one parameter
    389             GST_TYPE_BUFFER);
     362            GST_TYPE_SAMPLE);
    390363}
    391364
Note: See TracChangeset for help on using the changeset viewer.