Added qmafw-gst-subtitles-renderer-0.0.55 for Meego Harmattan 1.2
[mafwsubrenderer] / qmafw-gst-subtitles-renderer / src / MafwGstScreenshot.cpp
1 /*
2  * This file is part of QMAFW
3  *
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
5  * reserved.
6  *
7  * Contact: Visa Smolander <visa.smolander@nokia.com>
8  *
9  * This software, including documentation, is protected by copyright controlled
10  * by Nokia Corporation. All rights are reserved. Copying, including
11  * reproducing, storing, adapting or translating, any or all of this material
12  * requires the prior written consent of Nokia Corporation. This material also
13  * contains confidential information which may not be disclosed to others
14  * without the prior written consent of Nokia.
15  *
16  */
17
18 #include "MafwGstScreenshot.h"
19 #include <QDebug>
20
21 MafwGstScreenshot::MafwGstScreenshot(QObject *parent) : QObject(parent)
22 {
23     qDebug() << __PRETTY_FUNCTION__;
24
25     m_src = NULL;
26     m_sink = NULL;
27     m_pipeline = NULL;
28     m_filter = NULL;
29     m_csp = NULL;
30     m_enc = NULL;
31     m_bus = NULL;
32     m_caps = NULL;
33     m_structure = NULL;
34     m_handler_id = 0;
35 }
36
37 MafwGstScreenshot::~MafwGstScreenshot()
38 {
39     qDebug() << __PRETTY_FUNCTION__;
40     if(m_pipeline)
41     {
42         gst_element_set_state(m_pipeline, GST_STATE_NULL);
43         gst_object_unref(m_pipeline);
44     }
45 }
46
47 static void copyBufferToSource(GstElement *src, GstBuffer *buffer, GstPad *pad,
48                          gpointer data)
49 {
50
51     Q_UNUSED(src);
52     Q_UNUSED(pad);
53
54     GstBuffer *in_buf = GST_BUFFER(data);
55
56     memcpy(GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(in_buf),
57            GST_BUFFER_SIZE(in_buf));
58     GST_BUFFER_SIZE(buffer) = GST_BUFFER_SIZE(in_buf);
59 }
60
61 static void freeSourceBuffer(gpointer data)
62 {
63     GstBuffer *in_buf = GST_BUFFER(data);
64     gst_buffer_unref(in_buf);
65 }
66
67 static gboolean asyncBusHandler(GstBus *bus, GstMessage *msg, gpointer data)
68 {
69     Q_UNUSED(bus);
70
71     gboolean ret = TRUE;
72
73     MafwGstScreenshot *self = static_cast<MafwGstScreenshot*>(data);
74
75     switch(GST_MESSAGE_TYPE(msg))
76     {
77         case GST_MESSAGE_EOS:
78         {
79             ret = self->reportBack(NULL);
80             break;
81         }
82         case GST_MESSAGE_ERROR:
83         {
84             GError *error = NULL;
85
86             gst_message_parse_error(msg, &error, NULL);
87
88             ret = self->reportBack(error);
89             g_error_free(error);
90             break;
91         }
92         default:
93             break;
94     }
95     return ret;
96 }
97
98 /********************************************************************
99  * MafwGstScreenshot::savePauseFrame
100  ********************************************************************/
101 bool MafwGstScreenshot::savePauseFrame(GstBuffer *buffer, const char *filename)
102 {
103     qDebug() << __PRETTY_FUNCTION__;
104
105     gint width = 0;
106     gint height = 0;
107
108     if(!m_pipeline)
109     {
110         m_pipeline = gst_pipeline_new("screenshot-pipeline");
111         if(!m_pipeline)
112         {
113             goto err_out;
114         }
115         m_src = gst_element_factory_make("fakesrc", NULL);
116         m_sink = gst_element_factory_make("filesink", NULL);
117         m_filter = gst_element_factory_make("capsfilter", NULL);
118         m_csp = gst_element_factory_make("ffmpegcolorspace", NULL);
119         m_enc = gst_element_factory_make("pngenc", NULL);
120
121         if(!m_src || !m_sink || !m_filter || !m_csp || !m_enc)
122         {
123             goto err_out;
124         }
125
126         gst_bin_add_many(GST_BIN(m_pipeline), m_src, m_filter, m_csp, m_enc, m_sink, NULL);
127
128         if(!gst_element_link_many(m_src, m_filter, m_csp, m_enc, m_sink, NULL))
129         {
130             goto err_out;
131         }
132
133         m_bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
134         gst_bus_add_watch(m_bus, asyncBusHandler, this);
135         gst_object_unref(m_bus);
136
137         g_object_set(m_sink, "preroll-queue-len", 1, NULL);
138         g_object_set(m_src,
139                 "sizetype", 2,
140                 "num-buffers", 1,
141                 "signal-handoffs", TRUE,
142                 NULL);
143         g_object_set(m_enc, "compression-level", 1, NULL);
144     }
145
146     m_caps = gst_caps_copy(GST_BUFFER_CAPS(buffer));
147     if(!m_caps)
148     {
149         goto err_out;
150     }
151     m_structure = gst_caps_get_structure(m_caps, 0);
152     gst_structure_remove_field(m_structure, "pixel-aspect-ratio");
153     /* limit image size in case it exceeds the pre-determined size */
154     if(gst_structure_get_int(m_structure, "width", &width) &&
155        gst_structure_get_int(m_structure, "height", &height))
156     {
157         gst_caps_set_simple(m_caps,
158                             "width", G_TYPE_INT, width,
159                             "height", G_TYPE_INT, height,
160                             NULL);
161     }
162     g_object_set(m_filter, "caps", m_caps, NULL);
163     gst_caps_unref(m_caps);
164
165     g_object_set(m_sink, "location", filename, NULL);
166     g_object_set(m_src, "sizemax", GST_BUFFER_SIZE(buffer), NULL);
167
168     m_handler_id = g_signal_connect_data(m_src, "handoff", G_CALLBACK(copyBufferToSource), buffer, (GClosureNotify) freeSourceBuffer, G_CONNECT_AFTER);
169
170     gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
171
172     return true;
173
174 err_out:
175     if( m_pipeline )
176     {
177         gst_object_unref(m_pipeline);
178         m_pipeline = NULL;
179     }
180     if( buffer )
181     {
182         gst_buffer_unref(buffer);
183     }
184
185     return false;
186 }
187
188 /********************************************************************
189  * MafwGstScreenshot::cancelPauseFrame
190  ********************************************************************/
191 void MafwGstScreenshot::cancelPauseFrame()
192 {
193     qDebug() << __PRETTY_FUNCTION__;
194
195     gst_element_set_state(m_pipeline, GST_STATE_NULL);
196     g_signal_handler_disconnect(m_src, m_handler_id);
197
198     Q_EMIT screenshotCancelled();
199 }
200
201 /********************************************************************
202  * MafwGstScreenshot::reportBack
203  ********************************************************************/
204 bool MafwGstScreenshot::reportBack(GError *error)
205 {
206     qDebug() << __PRETTY_FUNCTION__;
207     if(!error)
208     {
209         char *location;
210         g_object_get(m_sink, "location", &location, NULL);
211         Q_EMIT screenshotTaken(location, NULL);
212         g_free(location);
213     }
214     else
215     {
216         Q_EMIT screenshotTaken(NULL, error);
217     }
218
219     gst_element_set_state(m_pipeline, GST_STATE_NULL);
220     g_signal_handler_disconnect(m_src, m_handler_id);
221
222     return true;
223 }