--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwGstScreenshot.h"
+#include <QDebug>
+
+MafwGstScreenshot::MafwGstScreenshot(QObject *parent) : QObject(parent)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_src = NULL;
+ m_sink = NULL;
+ m_pipeline = NULL;
+ m_filter = NULL;
+ m_csp = NULL;
+ m_enc = NULL;
+ m_bus = NULL;
+ m_caps = NULL;
+ m_structure = NULL;
+ m_handler_id = 0;
+}
+
+MafwGstScreenshot::~MafwGstScreenshot()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ if(m_pipeline)
+ {
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ gst_object_unref(m_pipeline);
+ }
+}
+
+static void copyBufferToSource(GstElement *src, GstBuffer *buffer, GstPad *pad,
+ gpointer data)
+{
+
+ Q_UNUSED(src);
+ Q_UNUSED(pad);
+
+ GstBuffer *in_buf = GST_BUFFER(data);
+
+ memcpy(GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(in_buf),
+ GST_BUFFER_SIZE(in_buf));
+ GST_BUFFER_SIZE(buffer) = GST_BUFFER_SIZE(in_buf);
+}
+
+static void freeSourceBuffer(gpointer data)
+{
+ GstBuffer *in_buf = GST_BUFFER(data);
+ gst_buffer_unref(in_buf);
+}
+
+static gboolean asyncBusHandler(GstBus *bus, GstMessage *msg, gpointer data)
+{
+ Q_UNUSED(bus);
+
+ gboolean ret = TRUE;
+
+ MafwGstScreenshot *self = static_cast<MafwGstScreenshot*>(data);
+
+ switch(GST_MESSAGE_TYPE(msg))
+ {
+ case GST_MESSAGE_EOS:
+ {
+ ret = self->reportBack(NULL);
+ break;
+ }
+ case GST_MESSAGE_ERROR:
+ {
+ GError *error = NULL;
+
+ gst_message_parse_error(msg, &error, NULL);
+
+ ret = self->reportBack(error);
+ g_error_free(error);
+ break;
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
+/********************************************************************
+ * MafwGstScreenshot::savePauseFrame
+ ********************************************************************/
+bool MafwGstScreenshot::savePauseFrame(GstBuffer *buffer, const char *filename)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ gint width = 0;
+ gint height = 0;
+
+ if(!m_pipeline)
+ {
+ m_pipeline = gst_pipeline_new("screenshot-pipeline");
+ if(!m_pipeline)
+ {
+ goto err_out;
+ }
+ m_src = gst_element_factory_make("fakesrc", NULL);
+ m_sink = gst_element_factory_make("filesink", NULL);
+ m_filter = gst_element_factory_make("capsfilter", NULL);
+ m_csp = gst_element_factory_make("ffmpegcolorspace", NULL);
+ m_enc = gst_element_factory_make("pngenc", NULL);
+
+ if(!m_src || !m_sink || !m_filter || !m_csp || !m_enc)
+ {
+ goto err_out;
+ }
+
+ gst_bin_add_many(GST_BIN(m_pipeline), m_src, m_filter, m_csp, m_enc, m_sink, NULL);
+
+ if(!gst_element_link_many(m_src, m_filter, m_csp, m_enc, m_sink, NULL))
+ {
+ goto err_out;
+ }
+
+ m_bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
+ gst_bus_add_watch(m_bus, asyncBusHandler, this);
+ gst_object_unref(m_bus);
+
+ g_object_set(m_sink, "preroll-queue-len", 1, NULL);
+ g_object_set(m_src,
+ "sizetype", 2,
+ "num-buffers", 1,
+ "signal-handoffs", TRUE,
+ NULL);
+ g_object_set(m_enc, "compression-level", 1, NULL);
+ }
+
+ m_caps = gst_caps_copy(GST_BUFFER_CAPS(buffer));
+ if(!m_caps)
+ {
+ goto err_out;
+ }
+ m_structure = gst_caps_get_structure(m_caps, 0);
+ gst_structure_remove_field(m_structure, "pixel-aspect-ratio");
+ /* limit image size in case it exceeds the pre-determined size */
+ if(gst_structure_get_int(m_structure, "width", &width) &&
+ gst_structure_get_int(m_structure, "height", &height))
+ {
+ gst_caps_set_simple(m_caps,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ }
+ g_object_set(m_filter, "caps", m_caps, NULL);
+ gst_caps_unref(m_caps);
+
+ g_object_set(m_sink, "location", filename, NULL);
+ g_object_set(m_src, "sizemax", GST_BUFFER_SIZE(buffer), NULL);
+
+ m_handler_id = g_signal_connect_data(m_src, "handoff", G_CALLBACK(copyBufferToSource), buffer, (GClosureNotify) freeSourceBuffer, G_CONNECT_AFTER);
+
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+
+ return true;
+
+err_out:
+ if( m_pipeline )
+ {
+ gst_object_unref(m_pipeline);
+ m_pipeline = NULL;
+ }
+ if( buffer )
+ {
+ gst_buffer_unref(buffer);
+ }
+
+ return false;
+}
+
+/********************************************************************
+ * MafwGstScreenshot::cancelPauseFrame
+ ********************************************************************/
+void MafwGstScreenshot::cancelPauseFrame()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ g_signal_handler_disconnect(m_src, m_handler_id);
+
+ Q_EMIT screenshotCancelled();
+}
+
+/********************************************************************
+ * MafwGstScreenshot::reportBack
+ ********************************************************************/
+bool MafwGstScreenshot::reportBack(GError *error)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ if(!error)
+ {
+ char *location;
+ g_object_get(m_sink, "location", &location, NULL);
+ Q_EMIT screenshotTaken(location, NULL);
+ g_free(location);
+ }
+ else
+ {
+ Q_EMIT screenshotTaken(NULL, error);
+ }
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ g_signal_handler_disconnect(m_src, m_handler_id);
+
+ return true;
+}