/*
 * Copyright (C) 2018 Metrological Group B.V.
 * Author: Thibault Saunier <tsaunier@igalia.com>
 * Author: Alejandro G. Castro <alex@igalia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * aint with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#if ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
#include "GStreamerMediaStreamSource.h"

#include "AudioTrackPrivate.h"
#include "GStreamerAudioData.h"
#include "GStreamerCommon.h"
#include "GStreamerVideoCaptureSource.h"
#include "MediaSampleGStreamer.h"
#include "VideoTrackPrivate.h"

#include <gst/app/gstappsrc.h>
#include <gst/base/gstflowcombiner.h>

namespace WebCore {

static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc* self, GstSample* gstsample);
static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc* self, GstSample* gstsample);
static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate&);
static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc* self, RealtimeMediaSource::Type trackType);

static GstStaticPadTemplate videoSrcTemplate = GST_STATIC_PAD_TEMPLATE("video_src",
    GST_PAD_SRC,
    GST_PAD_SOMETIMES,
    GST_STATIC_CAPS("video/x-raw;video/x-h264;video/x-vp8"));

static GstStaticPadTemplate audioSrcTemplate = GST_STATIC_PAD_TEMPLATE("audio_src",
    GST_PAD_SRC,
    GST_PAD_SOMETIMES,
    GST_STATIC_CAPS("audio/x-raw(ANY);"));

static GstTagList* mediaStreamTrackPrivateGetTags(MediaStreamTrackPrivate* track)
{
    auto taglist = gst_tag_list_new_empty();

    if (!track->label().isEmpty()) {
        gst_tag_list_add(taglist, GST_TAG_MERGE_APPEND,
            GST_TAG_TITLE, track->label().utf8().data(), nullptr);
    }

    if (track->type() == RealtimeMediaSource::Type::Audio) {
        gst_tag_list_add(taglist, GST_TAG_MERGE_APPEND, WEBKIT_MEDIA_TRACK_TAG_KIND,
            static_cast<int>(AudioTrackPrivate::Kind::Main), nullptr);
    } else if (track->type() == RealtimeMediaSource::Type::Video) {
        gst_tag_list_add(taglist, GST_TAG_MERGE_APPEND, WEBKIT_MEDIA_TRACK_TAG_KIND,
            static_cast<int>(VideoTrackPrivate::Kind::Main), nullptr);

        if (track->isCaptureTrack()) {
            GStreamerVideoCaptureSource& source = static_cast<GStreamerVideoCaptureSource&>(
                track->source());

            gst_tag_list_add(taglist, GST_TAG_MERGE_APPEND,
                WEBKIT_MEDIA_TRACK_TAG_WIDTH, source.size().width(),
                WEBKIT_MEDIA_TRACK_TAG_HEIGHT, source.size().height(), nullptr);
        }
    }

    return taglist;
}

GstStream* webkitMediaStreamNew(MediaStreamTrackPrivate* track)
{
    GRefPtr<GstCaps> caps;
    GstStreamType type;

    if (track->type() == RealtimeMediaSource::Type::Audio) {
        caps = adoptGRef(gst_static_pad_template_get_caps(&audioSrcTemplate));
        type = GST_STREAM_TYPE_AUDIO;
    } else if (track->type() == RealtimeMediaSource::Type::Video) {
        caps = adoptGRef(gst_static_pad_template_get_caps(&videoSrcTemplate));
        type = GST_STREAM_TYPE_VIDEO;
    } else {
        GST_FIXME("Handle %d type", static_cast<int>(track->type()));

        return nullptr;
    }

    auto gststream = (GstStream*)gst_stream_new(track->id().utf8().data(),
        caps.get(), type, GST_STREAM_FLAG_SELECT);
    auto tags = adoptGRef(mediaStreamTrackPrivateGetTags(track));
    gst_stream_set_tags(gststream, tags.get());

    return gststream;
}

class WebKitMediaStreamTrackObserver
    : public MediaStreamTrackPrivate::Observer {
    WTF_MAKE_FAST_ALLOCATED;
public:
    virtual ~WebKitMediaStreamTrackObserver() { };
    WebKitMediaStreamTrackObserver(WebKitMediaStreamSrc* src)
        : m_mediaStreamSrc(src) { }
    void trackStarted(MediaStreamTrackPrivate&) final { };

    void trackEnded(MediaStreamTrackPrivate& track) final
    {
        webkitMediaStreamSrcTrackEnded(m_mediaStreamSrc, track);
    }

    void trackMutedChanged(MediaStreamTrackPrivate&) final { };
    void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
    void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
    void readyStateChanged(MediaStreamTrackPrivate&) final { };

    void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample& sample) final
    {
        auto gstsample = static_cast<MediaSampleGStreamer*>(&sample)->platformSample().sample.gstSample;

        webkitMediaStreamSrcPushVideoSample(m_mediaStreamSrc, gstsample);
    }

    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData& audioData, const AudioStreamDescription&, size_t) final
    {
        auto audiodata = static_cast<const GStreamerAudioData&>(audioData);

        webkitMediaStreamSrcPushAudioSample(m_mediaStreamSrc, audiodata.getSample());
    }

private:
    WebKitMediaStreamSrc* m_mediaStreamSrc;
};

class WebKitMediaStreamObserver
    : public MediaStreamPrivate::Observer {
    WTF_MAKE_FAST_ALLOCATED;
public:
    virtual ~WebKitMediaStreamObserver() { };
    WebKitMediaStreamObserver(WebKitMediaStreamSrc* src)
        : m_mediaStreamSrc(src) { }

    void characteristicsChanged() final { GST_DEBUG_OBJECT(m_mediaStreamSrc.get(), "renegotiation should happen"); }
    void activeStatusChanged() final { }

    void didAddTrack(MediaStreamTrackPrivate& track) final
    {
        webkitMediaStreamSrcAddTrack(m_mediaStreamSrc.get(), &track, false);
    }

    void didRemoveTrack(MediaStreamTrackPrivate& track) final
    {
        webkitMediaStreamSrcRemoveTrackByType(m_mediaStreamSrc.get(), track.type());
    }

private:
    GRefPtr<WebKitMediaStreamSrc> m_mediaStreamSrc;
};

typedef struct _WebKitMediaStreamSrcClass WebKitMediaStreamSrcClass;
struct _WebKitMediaStreamSrc {
    GstBin parent_instance;

    gchar* uri;

    struct SourceData {
        GRefPtr<GstElement> m_src;
        void reset(bool isVideo)
        {
            m_firstBufferPts = GST_CLOCK_TIME_NONE;
            m_isVideo = isVideo;
            m_src = nullptr;
        }

        GstElement* src()
        {
            return m_src.get();
        }

        static void needDataCb(GstElement*, guint, WebKitMediaStreamSrc::SourceData *self)
        {
            self->setEnoughData(false);
        }

        static void enoughDataCb(GstElement*, WebKitMediaStreamSrc::SourceData *self)
        {
            self->setEnoughData(true);
        }


        void setSrc(GstElement *src)
        {
            m_src = adoptGRef(GST_ELEMENT(g_object_ref_sink(src)));
            if (GST_IS_APP_SRC(src)) {
                g_object_set(src, "is-live", true, "format", GST_FORMAT_TIME, "emit-signals", TRUE, "min-percent", 100, nullptr);
                g_signal_connect(src, "enough-data", G_CALLBACK(enoughDataCb), this);
                g_signal_connect(src, "need-data", G_CALLBACK(needDataCb), this);
            }
        }

        bool isUsed()
        {
            return !!m_src;
        }

        void setEnoughData(bool enough)
        {
            m_enoughData = enough;
        }

        void pushSample(GstSample *sample)
        {
            if (!m_src)
                return;

            bool drop = m_enoughData;
            auto buffer = gst_sample_get_buffer(sample);
            auto caps = gst_sample_get_caps(sample);
            if (!GST_CLOCK_TIME_IS_VALID(m_firstBufferPts)) {
                m_firstBufferPts = GST_BUFFER_PTS(buffer);
                auto pad = adoptGRef(gst_element_get_static_pad(m_src.get(), "src"));
                gst_pad_set_offset(pad.get(), -m_firstBufferPts);
            }

            if (m_isVideo && drop) {
                drop = (gst_structure_has_name(gst_caps_get_structure(caps, 0), "video/x-raw")
                    || GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT));
            }

            if (drop) {
                m_needsDiscont = true;
                GST_INFO_OBJECT(m_src.get(), "%s queue full already... not pushing", m_isVideo ? "Video" : "Audio");
                return;
            }

            if (m_needsDiscont) {
                GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DISCONT);
                m_needsDiscont = false;
            }

            gst_app_src_push_sample(GST_APP_SRC(m_src.get()), sample);
        }
    private:
        GstClockTime m_firstBufferPts;
        bool m_enoughData;
        bool m_needsDiscont;
        bool m_isVideo;
    };

    SourceData audioSrc;
    SourceData videoSrc;

    std::unique_ptr<WebKitMediaStreamTrackObserver> mediaStreamTrackObserver;
    std::unique_ptr<WebKitMediaStreamObserver> mediaStreamObserver;
    volatile gint npads;
    RefPtr<MediaStreamPrivate> stream;
    RefPtr<MediaStreamTrackPrivate> track;

    GstFlowCombiner* flowCombiner;
    GRefPtr<GstStreamCollection> streamCollection;
};

struct _WebKitMediaStreamSrcClass {
    GstBinClass parent_class;
};

enum {
    PROP_0,
    PROP_IS_LIVE,
    PROP_LAST
};

static GstURIType webkit_media_stream_src_uri_get_type(GType)
{
    return GST_URI_SRC;
}

static const gchar* const* webkit_media_stream_src_uri_get_protocols(GType)
{
    static const gchar* protocols[] = { "mediastream", nullptr };

    return protocols;
}

static gchar* webkit_media_stream_src_uri_get_uri(GstURIHandler* handler)
{
    WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(handler);

    /* FIXME: make thread-safe */
    return g_strdup(self->uri);
}

static gboolean webkitMediaStreamSrcUriSetUri(GstURIHandler* handler, const gchar* uri,
    GError**)
{
    WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(handler);
    self->uri = g_strdup(uri);

    return TRUE;
}

static void webkitMediaStreamSrcUriHandlerInit(gpointer g_iface, gpointer)
{
    GstURIHandlerInterface* iface = (GstURIHandlerInterface*)g_iface;

    iface->get_type = webkit_media_stream_src_uri_get_type;
    iface->get_protocols = webkit_media_stream_src_uri_get_protocols;
    iface->get_uri = webkit_media_stream_src_uri_get_uri;
    iface->set_uri = webkitMediaStreamSrcUriSetUri;
}

GST_DEBUG_CATEGORY_STATIC(webkitMediaStreamSrcDebug);
#define GST_CAT_DEFAULT webkitMediaStreamSrcDebug

#define doInit                                                                                                                                                              \
    G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, webkitMediaStreamSrcUriHandlerInit);                                                                                    \
    GST_DEBUG_CATEGORY_INIT(webkitMediaStreamSrcDebug, "webkitwebmediastreamsrc", 0, "mediastreamsrc element");                                                           \
    gst_tag_register_static(WEBKIT_MEDIA_TRACK_TAG_WIDTH, GST_TAG_FLAG_META, G_TYPE_INT, "Webkit MediaStream width", "Webkit MediaStream width", gst_tag_merge_use_first);    \
    gst_tag_register_static(WEBKIT_MEDIA_TRACK_TAG_HEIGHT, GST_TAG_FLAG_META, G_TYPE_INT, "Webkit MediaStream height", "Webkit MediaStream height", gst_tag_merge_use_first); \
    gst_tag_register_static(WEBKIT_MEDIA_TRACK_TAG_KIND, GST_TAG_FLAG_META, G_TYPE_INT, "Webkit MediaStream Kind", "Webkit MediaStream Kind", gst_tag_merge_use_first);

G_DEFINE_TYPE_WITH_CODE(WebKitMediaStreamSrc, webkit_media_stream_src, GST_TYPE_BIN, doInit);

static void webkitMediaStreamSrcSetProperty(GObject* object, guint prop_id,
    const GValue*, GParamSpec* pspec)
{
    switch (prop_id) {
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
        break;
    }
}

static void webkitMediaStreamSrcGetProperty(GObject* object, guint prop_id, GValue* value,
    GParamSpec* pspec)
{
    switch (prop_id) {
    case PROP_IS_LIVE:
        g_value_set_boolean(value, TRUE);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
        break;
    }
}

static void webkitMediaStreamSrcDispose(GObject* object)
{
    WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object);

    if (self->audioSrc.isUsed()) {
        gst_bin_remove(GST_BIN(self), self->audioSrc.src());
        self->audioSrc.reset(false);
    }

    if (self->videoSrc.isUsed()) {
        gst_bin_remove(GST_BIN(self), self->videoSrc.src());
        self->videoSrc.reset(true);
    }
}

static void webkitMediaStreamSrcFinalize(GObject* object)
{
    WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object);

    GST_OBJECT_LOCK(self);
    if (self->stream) {
        for (auto& track : self->stream->tracks())
            track->removeObserver(*self->mediaStreamTrackObserver.get());

        self->stream->removeObserver(*self->mediaStreamObserver);
        self->stream = nullptr;
    }
    GST_OBJECT_UNLOCK(self);

    g_clear_pointer(&self->uri, g_free);
    gst_flow_combiner_free(self->flowCombiner);
}

static GstStateChangeReturn webkitMediaStreamSrcChangeState(GstElement* element, GstStateChange transition)
{
    GstStateChangeReturn result;
    auto* self = WEBKIT_MEDIA_STREAM_SRC(element);

    if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {

        GST_OBJECT_LOCK(self);
        if (self->stream) {
            for (auto& track : self->stream->tracks())
                track->removeObserver(*self->mediaStreamTrackObserver.get());
        } else if (self->track)
            self->track->removeObserver(*self->mediaStreamTrackObserver.get());
        GST_OBJECT_UNLOCK(self);
    }

    result = GST_ELEMENT_CLASS(webkit_media_stream_src_parent_class)->change_state(element, transition);

    if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
        result = GST_STATE_CHANGE_NO_PREROLL;

    return result;
}

static void webkit_media_stream_src_class_init(WebKitMediaStreamSrcClass* klass)
{
    GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
    GstElementClass* gstelement_klass = GST_ELEMENT_CLASS(klass);

    gobject_class->finalize = webkitMediaStreamSrcFinalize;
    gobject_class->dispose = webkitMediaStreamSrcDispose;
    gobject_class->get_property = webkitMediaStreamSrcGetProperty;
    gobject_class->set_property = webkitMediaStreamSrcSetProperty;

    g_object_class_install_property(gobject_class, PROP_IS_LIVE,
        g_param_spec_boolean("is-live", "Is Live",
            "Let playbin3 know we are a live source.",
            TRUE, (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));

    gstelement_klass->change_state = webkitMediaStreamSrcChangeState;
    gst_element_class_add_pad_template(gstelement_klass,
        gst_static_pad_template_get(&videoSrcTemplate));
    gst_element_class_add_pad_template(gstelement_klass,
        gst_static_pad_template_get(&audioSrcTemplate));
}

static void webkit_media_stream_src_init(WebKitMediaStreamSrc* self)
{
    self->mediaStreamTrackObserver = makeUnique<WebKitMediaStreamTrackObserver>(self);
    self->mediaStreamObserver = makeUnique<WebKitMediaStreamObserver>(self);
    self->flowCombiner = gst_flow_combiner_new();
    self->videoSrc.reset(true);
    self->audioSrc.reset(false);
}

typedef struct {
    WebKitMediaStreamSrc* self;
    RefPtr<MediaStreamTrackPrivate> track;
    GstStaticPadTemplate* pad_template;
} ProbeData;

static GstFlowReturn webkitMediaStreamSrcChain(GstPad* pad, GstObject* parent, GstBuffer* buffer)
{
    GstFlowReturn result, chain_result;
    GRefPtr<WebKitMediaStreamSrc> self = adoptGRef(WEBKIT_MEDIA_STREAM_SRC(gst_object_get_parent(parent)));

    chain_result = gst_proxy_pad_chain_default(pad, GST_OBJECT(self.get()), buffer);
    result = gst_flow_combiner_update_pad_flow(self.get()->flowCombiner, pad, chain_result);

    if (result == GST_FLOW_FLUSHING)
        return chain_result;

    return result;
}

static void webkitMediaStreamSrcAddPad(WebKitMediaStreamSrc* self, GstPad* target, GstStaticPadTemplate* pad_template)
{
    auto padname = makeString("src_", g_atomic_int_add(&(self->npads), 1));
    auto ghostpad = gst_ghost_pad_new_from_template(padname.utf8().data(), target,
        gst_static_pad_template_get(pad_template));

    GST_DEBUG_OBJECT(self, "%s Ghosting %" GST_PTR_FORMAT,
        gst_object_get_path_string(GST_OBJECT_CAST(self)),
        target);

    auto proxypad = adoptGRef(GST_PAD(gst_proxy_pad_get_internal(GST_PROXY_PAD(ghostpad))));
    gst_pad_set_active(ghostpad, TRUE);
    if (!gst_element_add_pad(GST_ELEMENT(self), GST_PAD(ghostpad))) {
        GST_ERROR_OBJECT(self, "Could not add pad %s:%s", GST_DEBUG_PAD_NAME(ghostpad));
        ASSERT_NOT_REACHED();

        return;
    }

    gst_flow_combiner_add_pad(self->flowCombiner, proxypad.get());
    gst_pad_set_chain_function(proxypad.get(),
        static_cast<GstPadChainFunction>(webkitMediaStreamSrcChain));
}

static GstPadProbeReturn webkitMediaStreamSrcPadProbeCb(GstPad* pad, GstPadProbeInfo* info, ProbeData* data)
{
    GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info);
    WebKitMediaStreamSrc* self = data->self;

    switch (GST_EVENT_TYPE(event)) {
    case GST_EVENT_STREAM_START: {
        const gchar* stream_id;
        GRefPtr<GstStream> stream = nullptr;

        gst_event_parse_stream_start(event, &stream_id);
        if (!g_strcmp0(stream_id, data->track->id().utf8().data())) {
            GST_INFO_OBJECT(pad, "Event has been sticked already");
            return GST_PAD_PROBE_OK;
        }

        auto stream_start = gst_event_new_stream_start(data->track->id().utf8().data());
        gst_event_set_group_id(stream_start, 1);
        gst_event_unref(event);

        gst_pad_push_event(pad, stream_start);
        gst_pad_push_event(pad, gst_event_new_tag(mediaStreamTrackPrivateGetTags(data->track.get())));

        webkitMediaStreamSrcAddPad(self, pad, data->pad_template);

        return GST_PAD_PROBE_HANDLED;
    }
    default:
        break;
    }

    return GST_PAD_PROBE_OK;
}

static gboolean webkitMediaStreamSrcSetupSrc(WebKitMediaStreamSrc* self,
    MediaStreamTrackPrivate* track, GstElement* element,
    GstStaticPadTemplate* pad_template, gboolean observe_track,
    bool onlyTrack)
{
    auto pad = adoptGRef(gst_element_get_static_pad(element, "src"));

    gst_bin_add(GST_BIN(self), element);

    if (!onlyTrack) {
        ProbeData* data = new ProbeData;
        data->self = WEBKIT_MEDIA_STREAM_SRC(self);
        data->pad_template = pad_template;
        data->track = track;

        gst_pad_add_probe(pad.get(), (GstPadProbeType)GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
            (GstPadProbeCallback)webkitMediaStreamSrcPadProbeCb, data,
            [](gpointer data) {
                delete (ProbeData*)data;
            });
    } else
        webkitMediaStreamSrcAddPad(self, pad.get(), pad_template);

    if (observe_track)
        track->addObserver(*self->mediaStreamTrackObserver.get());

    gst_element_sync_state_with_parent(element);
    return TRUE;
}

static gboolean webkitMediaStreamSrcSetupAppSrc(WebKitMediaStreamSrc* self,
    MediaStreamTrackPrivate* track, WebKitMediaStreamSrc::SourceData* data,
    GstStaticPadTemplate* pad_template, bool onlyTrack)
{
    data->setSrc(gst_element_factory_make("appsrc", nullptr));
    if (track->isCaptureTrack())
        g_object_set(data->src(), "do-timestamp", true, nullptr);

    return webkitMediaStreamSrcSetupSrc(self, track, data->src(), pad_template, TRUE, onlyTrack);
}

static void webkitMediaStreamSrcPostStreamCollection(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream)
{
    GST_OBJECT_LOCK(self);
    self->streamCollection = adoptGRef(gst_stream_collection_new(stream->id().utf8().data()));
    for (auto& track : stream->tracks()) {
        auto gststream = webkitMediaStreamNew(track.get());

        gst_stream_collection_add_stream(self->streamCollection.get(), gststream);
    }
    GST_OBJECT_UNLOCK(self);

    gst_element_post_message(GST_ELEMENT(self),
        gst_message_new_stream_collection(GST_OBJECT(self), self->streamCollection.get()));
}

bool webkitMediaStreamSrcAddTrack(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate* track, bool onlyTrack)
{
    bool res = false;
    if (track->type() == RealtimeMediaSource::Type::Audio)
        res = webkitMediaStreamSrcSetupAppSrc(self, track, &self->audioSrc, &audioSrcTemplate, onlyTrack);
    else if (track->type() == RealtimeMediaSource::Type::Video)
        res = webkitMediaStreamSrcSetupAppSrc(self, track, &self->videoSrc, &videoSrcTemplate, onlyTrack);
    else
        GST_INFO("Unsupported track type: %d", static_cast<int>(track->type()));

    if (onlyTrack && res)
        self->track = track;

    return false;
}

static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc* self, RealtimeMediaSource::Type trackType)
{
    if (trackType == RealtimeMediaSource::Type::Audio) {
        if (self->audioSrc.isUsed()) {
            gst_element_set_state(self->audioSrc.src(), GST_STATE_NULL);
            gst_bin_remove(GST_BIN(self), self->audioSrc.src());
            self->audioSrc.reset(false);
        }
    } else if (trackType == RealtimeMediaSource::Type::Video) {
        if (self->videoSrc.isUsed()) {
            gst_element_set_state(self->videoSrc.src(), GST_STATE_NULL);
            gst_bin_remove(GST_BIN(self), self->videoSrc.src());
            self->videoSrc.reset(true);
        }
    } else
        GST_INFO("Unsupported track type: %d", static_cast<int>(trackType));
}

bool webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream)
{
    ASSERT(WEBKIT_IS_MEDIA_STREAM_SRC(self));

    webkitMediaStreamSrcRemoveTrackByType(self, RealtimeMediaSource::Type::Audio);
    webkitMediaStreamSrcRemoveTrackByType(self, RealtimeMediaSource::Type::Video);

    webkitMediaStreamSrcPostStreamCollection(self, stream);

    self->stream = stream;
    self->stream->addObserver(*self->mediaStreamObserver.get());
    for (auto& track : stream->tracks())
        webkitMediaStreamSrcAddTrack(self, track.get(), false);

    return TRUE;
}

static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc* self, GstSample* gstsample)
{
    self->videoSrc.pushSample(gstsample);
}

static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc* self, GstSample* gstsample)
{
    self->audioSrc.pushSample(gstsample);
}

static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self,
    MediaStreamTrackPrivate& track)
{
    GRefPtr<GstPad> pad = nullptr;

    GST_OBJECT_LOCK(self);
    for (auto tmp = GST_ELEMENT(self)->srcpads; tmp; tmp = tmp->next) {
        GstPad* tmppad = GST_PAD(tmp->data);
        const gchar* stream_id;

        GstEvent* stream_start = gst_pad_get_sticky_event(tmppad, GST_EVENT_STREAM_START, 0);
        if (!stream_start)
            continue;

        gst_event_parse_stream_start(stream_start, &stream_id);
        if (String(stream_id) == track.id()) {
            pad = tmppad;
            break;
        }
    }
    GST_OBJECT_UNLOCK(self);

    if (!pad) {
        GST_ERROR_OBJECT(self, "No pad found for %s", track.id().utf8().data());

        return;
    }

    // Make sure that the video.videoWidth is reset to 0
    webkitMediaStreamSrcPostStreamCollection(self, self->stream.get());
    auto tags = mediaStreamTrackPrivateGetTags(&track);
    gst_pad_push_event(pad.get(), gst_event_new_tag(tags));
    gst_pad_push_event(pad.get(), gst_event_new_eos());
}

GstElement* webkitMediaStreamSrcNew(void)
{
    return GST_ELEMENT(g_object_new(webkit_media_stream_src_get_type(), nullptr));
}

} // WebCore

#endif // ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC)
