/*
 *  Copyright (C) 2022 Igalia, S.L
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "DMABufVideoSinkGStreamer.h"

#if ENABLE(VIDEO)

#include "GStreamerCommon.h"
#include "GStreamerVideoSinkCommon.h"
#include <gst/allocators/gstdmabuf.h>
#include <mutex>
#include <wtf/glib/WTFGType.h>

using namespace WebCore;

enum {
    PROP_0,
    PROP_STATS,
    PROP_LAST
};

struct _WebKitDMABufVideoSinkPrivate {
    GRefPtr<GstElement> appSink;
    MediaPlayerPrivateGStreamer* mediaPlayerPrivate;
};

GST_DEBUG_CATEGORY_STATIC(webkit_dmabuf_video_sink_debug);
#define GST_CAT_DEFAULT webkit_dmabuf_video_sink_debug

#define GST_WEBKIT_DMABUF_SINK_CAPS_FORMAT_LIST "{ RGBA, RGBx, BGRA, BGRx, I420, YV12, A420, NV12, NV21, Y444, Y41B, Y42B, VUYA }"
static GstStaticPadTemplate sinkTemplate = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);

// TODO: this is a list of remaining YUV formats we want to support, but don't currently work (due to improper handling in TextureMapper):
//     YUY2, YVYU, UYVY, VYUY, AYUV

#define webkit_dmabuf_video_sink_parent_class parent_class
WEBKIT_DEFINE_TYPE_WITH_CODE(WebKitDMABufVideoSink, webkit_dmabuf_video_sink, GST_TYPE_BIN,
    GST_DEBUG_CATEGORY_INIT(webkit_dmabuf_video_sink_debug, "webkitdmabufvideosink", 0, "DMABuf video sink element"))

// WEBKIT_GST_DMABUF_SINK_FORCED_FALLBACK_CAPS_FORMAT env can be used to force a specific format to be used as the only supported format
// by this sink. This is most useful for testing and debugging the rendering pipeline behavior for a given format.
static const char* forcedFallbackCapsFormat()
{
    static char s_format[64] { };
    static std::once_flag s_flag;
    std::call_once(s_flag,
        [&] {
            const char* format = g_getenv("WEBKIT_GST_DMABUF_SINK_FORCED_FALLBACK_CAPS_FORMAT");
            if (format)
                g_strlcpy(const_cast<char*>(s_format), format, 64);
            else
                s_format[0] = 0;
        });

    if (!s_format[0])
        return nullptr;
    return s_format;
}

static void webKitDMABufVideoSinkConstructed(GObject* object)
{
    GST_CALL_PARENT(G_OBJECT_CLASS, constructed, (object));

    WebKitDMABufVideoSink* sink = WEBKIT_DMABUF_VIDEO_SINK(object);

    sink->priv->appSink = makeGStreamerElement("appsink", "webkit-dmabuf-video-appsink");
    ASSERT(sink->priv->appSink);
    g_object_set(sink->priv->appSink.get(), "enable-last-sample", FALSE, "emit-signals", TRUE, "max-buffers", 1, nullptr);

    gst_bin_add(GST_BIN_CAST(sink), sink->priv->appSink.get());

    // This sink handles dmabuf data or raw data of any format in the supported format list.
    // The dmabuf and raw data types are the two types of data we can handle via this sink (in combination with functionality in
    // MediaPlayerPrivateGStreamer). The format list corresponds to the formats we are able to then handle in the graphics pipeline.
    // In case of dmabuf data, that dmabuf is handled most optimally and just relayed to the graphics pipeline.
    // In case of raw data, dmabuf objects are produced on the spot and filled with that data, and then pushed to the graphics pipeline.
    static GstStaticCaps s_dmabufCaps = GST_STATIC_CAPS(
        GST_VIDEO_CAPS_MAKE_WITH_FEATURES(GST_CAPS_FEATURE_MEMORY_DMABUF, GST_WEBKIT_DMABUF_SINK_CAPS_FORMAT_LIST));
    static GstStaticCaps s_fallbackCaps = GST_STATIC_CAPS(GST_VIDEO_CAPS_MAKE(GST_WEBKIT_DMABUF_SINK_CAPS_FORMAT_LIST));

    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_new_empty());
    {
        if (forcedFallbackCapsFormat()) {
            caps = gst_caps_new_simple("video/x-raw",
                "format", G_TYPE_STRING, forcedFallbackCapsFormat(), nullptr);
        } else {
            gst_caps_append(caps.get(), gst_static_caps_get(&s_dmabufCaps));
            gst_caps_append(caps.get(), gst_static_caps_get(&s_fallbackCaps));
        }
    }
    g_object_set(sink->priv->appSink.get(), "caps", caps.get(), nullptr);

    GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(sink->priv->appSink.get(), "sink"));
    gst_element_add_pad(GST_ELEMENT_CAST(sink), gst_ghost_pad_new("sink", pad.get()));
}

void webKitDMABufVideoSinkFinalize(GObject* object)
{
    ASSERT(isMainThread());

    WebKitDMABufVideoSink* sink = WEBKIT_DMABUF_VIDEO_SINK(object);
    WebKitDMABufVideoSinkPrivate* priv = sink->priv;

    if (priv->mediaPlayerPrivate)
        g_signal_handlers_disconnect_by_data(priv->appSink.get(), priv->mediaPlayerPrivate);

    GST_DEBUG_OBJECT(object, "WebKitDMABufVideoSink finalized.");

    GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object));
}

static void webKitDMABufVideoSinkGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* paramSpec)
{
    WebKitDMABufVideoSink* sink = WEBKIT_DMABUF_VIDEO_SINK(object);

    switch (propertyId) {
    case PROP_STATS:
        if (webkitGstCheckVersion(1, 18, 0)) {
            GUniqueOutPtr<GstStructure> stats;
            g_object_get(sink->priv->appSink.get(), "stats", &stats.outPtr(), nullptr);
            gst_value_set_structure(value, stats.get());
        }
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, paramSpec);
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}

static void webkit_dmabuf_video_sink_class_init(WebKitDMABufVideoSinkClass* klass)
{
    GObjectClass* objectClass = G_OBJECT_CLASS(klass);
    GstElementClass* elementClass = GST_ELEMENT_CLASS(klass);

    objectClass->constructed = webKitDMABufVideoSinkConstructed;
    objectClass->finalize = webKitDMABufVideoSinkFinalize;
    objectClass->get_property = webKitDMABufVideoSinkGetProperty;

    gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&sinkTemplate));
    gst_element_class_set_static_metadata(elementClass, "WebKit DMABuf video sink", "Sink/Video", "Renders video", "Zan Dobersek <zdobersek@igalia.com>");

    g_object_class_install_property(objectClass, PROP_STATS, g_param_spec_boxed("stats", "Statistics",
        "Sink Statistics", GST_TYPE_STRUCTURE, static_cast<GParamFlags>(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
}

bool webKitDMABufVideoSinkIsEnabled()
{
    static bool s_enabled = false;
    static std::once_flag s_flag;
    std::call_once(s_flag,
        [&] {
            const char* value = g_getenv("WEBKIT_GST_DMABUF_SINK_ENABLED");
            s_enabled = value && (equalLettersIgnoringASCIICase(value, "true"_s) || equalLettersIgnoringASCIICase(value, "1"_s));
        });
    return s_enabled;
}

bool webKitDMABufVideoSinkProbePlatform()
{
    return isGStreamerPluginAvailable("app");
}

void webKitDMABufVideoSinkSetMediaPlayerPrivate(WebKitDMABufVideoSink* sink, MediaPlayerPrivateGStreamer* player)
{
    WebKitDMABufVideoSinkPrivate* priv = sink->priv;

    priv->mediaPlayerPrivate = player;
    webKitVideoSinkSetMediaPlayerPrivate(priv->appSink.get(), priv->mediaPlayerPrivate);
}

#endif // ENABLE(VIDEO)
