/*
 * 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, "renegotiation should happen"); }
    void activeStatusChanged() final { }

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

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

private:
    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)
