/*
 * Copyright (C) 2010 Igalia S.L
 *
 * 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
 * along 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"
#include "ImageGStreamer.h"

#if ENABLE(VIDEO) && USE(GSTREAMER)

#include "GStreamerCommon.h"

#include <cairo.h>
#include <gst/gst.h>
#include <gst/video/gstvideometa.h>


namespace WebCore {

ImageGStreamer::ImageGStreamer(GstSample* sample)
{
    GstCaps* caps = gst_sample_get_caps(sample);
    GstVideoInfo videoInfo;
    gst_video_info_init(&videoInfo);
    if (!gst_video_info_from_caps(&videoInfo, caps))
        return;

    // The frame has to RGB so we can paint it.
    ASSERT(GST_VIDEO_INFO_IS_RGB(&videoInfo));

    GstBuffer* buffer = gst_sample_get_buffer(sample);
    if (UNLIKELY(!GST_IS_BUFFER(buffer)))
        return;

    m_frameMapped = gst_video_frame_map(&m_videoFrame, &videoInfo, buffer, GST_MAP_READ);
    if (!m_frameMapped)
        return;

    // The video buffer may have these formats in these cases:
    // { BGRx, BGRA }: on little endian:
    //   - When GStreamer-gl is disabled (being AC enabled or not) as VideoSinkGStreamer is used.
    //   - When GStreamer-gl is enabled, but the caps used in the sink are not RGB and it's converted by the player to paint it.
    // { xRGB, ARGB }: on big endian:
    //   - When GStreamer-gl is disabled (being AC enabled or not) as VideoSinkGStreamer is used.
    //   - When GStreamer-gl is enabled, but the caps used in the sink are not RGB and it's converted by the player to paint it.
    // { RGBx, RGBA }
    //   - When GStreamer-gl is enabled and the caps used in the sink are RGBx/RGBA.
    //
    // Internally cairo uses BGRA for CAIRO_FORMAT_ARGB32 on little endian and ARGB on big endian, so both { BGRx, BGRA }
    // and { xRGB, ARGB } can be passed directly to cairo. But for { RGBx, RGBA } we need to swap the R and B components.
    // Also, GStreamer uses straight alpha while cairo requires it to be premultiplied, so if the format has alpha
    // we need to premultiply the color components. So in these cases we need to create a modified copy of the original
    // buffer.
    m_hasAlpha = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo);
    bool componentSwapRequired = GST_VIDEO_FRAME_FORMAT(&m_videoFrame) == GST_VIDEO_FORMAT_RGBA || GST_VIDEO_FRAME_FORMAT(&m_videoFrame) == GST_VIDEO_FORMAT_RGBx;
    unsigned char* bufferData = reinterpret_cast<unsigned char*>(GST_VIDEO_FRAME_PLANE_DATA(&m_videoFrame, 0));
    int stride = GST_VIDEO_FRAME_PLANE_STRIDE(&m_videoFrame, 0);
    int width = GST_VIDEO_FRAME_WIDTH(&m_videoFrame);
    int height = GST_VIDEO_FRAME_HEIGHT(&m_videoFrame);
    RefPtr<cairo_surface_t> surface;

    if (m_hasAlpha || componentSwapRequired) {
        uint8_t* surfaceData = static_cast<uint8_t*>(fastMalloc(height * stride));
        uint8_t* surfacePixel = surfaceData;

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                // These store the source pixel components.
                uint16_t red;
                uint16_t green;
                uint16_t blue;
                uint16_t alpha;
                // These store the component offset inside the pixel for the destination surface.
                uint8_t redIndex;
                uint8_t greenIndex;
                uint8_t blueIndex;
                uint8_t alphaIndex;
                if (componentSwapRequired) {
                    // Source is RGBA or RGBx.
                    red = bufferData[0];
                    green = bufferData[1];
                    blue = bufferData[2];
                    alpha = bufferData[3];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
                    // Destination is BGRA.
                    redIndex = 2;
                    greenIndex = 1;
                    blueIndex = 0;
                    alphaIndex = 3;
#else
                    // Destination is ARGB.
                    redIndex = 1;
                    greenIndex = 2;
                    blueIndex = 3;
                    alphaIndex = 0;
#endif
                } else {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
                    // BGRA or BGRx both source and destination.
                    red = bufferData[2];
                    green = bufferData[1];
                    blue = bufferData[0];
                    alpha = bufferData[3];
                    redIndex = 2;
                    greenIndex = 1;
                    blueIndex = 0;
                    alphaIndex = 3;
#else
                    // ARGB ot xRGB both source and destination.
                    red = bufferData[1];
                    green = bufferData[2];
                    blue = bufferData[3];
                    alpha = bufferData[0];
                    redIndex = 1;
                    greenIndex = 2;
                    blueIndex = 3;
                    alphaIndex = 0;
#endif
                }

                if (m_hasAlpha) {
                    surfacePixel[redIndex] = red * alpha / 255;
                    surfacePixel[greenIndex] = green * alpha / 255;
                    surfacePixel[blueIndex] = blue * alpha / 255;
                    surfacePixel[alphaIndex] = alpha;
                } else {
                    surfacePixel[redIndex] = red;
                    surfacePixel[greenIndex] = green;
                    surfacePixel[blueIndex] = blue;
                    surfacePixel[alphaIndex] = alpha;
                }

                bufferData += 4;
                surfacePixel += 4;
            }
        }
        surface = adoptRef(cairo_image_surface_create_for_data(surfaceData, CAIRO_FORMAT_ARGB32, width, height, stride));
        static cairo_user_data_key_t s_surfaceDataKey;
        cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, surfaceData, [](void* data) { fastFree(data); });
    } else
        surface = adoptRef(cairo_image_surface_create_for_data(bufferData, CAIRO_FORMAT_ARGB32, width, height, stride));

    ASSERT(cairo_surface_status(surface.get()) == CAIRO_STATUS_SUCCESS);
    m_image = BitmapImage::create(WTFMove(surface));

    if (GstVideoCropMeta* cropMeta = gst_buffer_get_video_crop_meta(buffer))
        setCropRect(FloatRect(cropMeta->x, cropMeta->y, cropMeta->width, cropMeta->height));
}

ImageGStreamer::~ImageGStreamer()
{
    if (m_image)
        m_image = nullptr;

    // We keep the buffer memory mapped until the image is destroyed because the internal
    // cairo_surface_t was created using cairo_image_surface_create_for_data().
    if (m_frameMapped)
        gst_video_frame_unmap(&m_videoFrame);
}

} // namespace WebCore

#endif // USE(GSTREAMER)
