Added night framerate to image and video settings
[harmattan/cameraplus] / lib / qtcamviewfinderrenderergeneric.cpp
1 #include "qtcamviewfinderrenderergeneric.h"
2 #include <QDebug>
3 #include <gst/video/video.h>
4 #include <QPainter>
5 #include "qtcamconfig.h"
6
7 QT_CAM_VIEWFINDER_RENDERER(RENDERER_TYPE_GENERIC, QtCamViewfinderRendererGeneric);
8
9 #define CAPS "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, red_mask = (int) 65280, green_mask = (int) 16711680, blue_mask = (int) -16777216"
10
11 // TODO: this needs to be debugged or rewritten. There are race conditions.
12 QtCamViewfinderRendererGeneric::QtCamViewfinderRendererGeneric(QtCamConfig *config,
13                                                                QObject *parent) :
14   QtCamViewfinderRenderer(config, parent), m_elem(0), m_sink(0), m_id(0) {
15
16 }
17
18 QtCamViewfinderRendererGeneric::~QtCamViewfinderRendererGeneric() {
19   m_mutex.lock();
20
21   if (m_elem) {
22     g_object_remove_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
23     m_elem = 0;
24
25     g_signal_handler_disconnect(m_sink, m_id);
26   }
27
28   m_mutex.unlock();
29 }
30
31 void QtCamViewfinderRendererGeneric::paint(QPainter *painter) {
32   // TODO: scale and keep aspect ratio.
33   m_mutex.lock();
34
35   if (!m_image.isNull()) {
36     painter->drawImage(QRectF(QPointF(0, 0), m_size), m_image);
37   }
38
39   m_mutex.unlock();
40 }
41
42 void QtCamViewfinderRendererGeneric::resize(const QSizeF& size) {
43   m_size = size;
44 }
45
46 void QtCamViewfinderRendererGeneric::reset() {
47   m_image = QImage();
48 }
49
50 GstElement *QtCamViewfinderRendererGeneric::sinkElement() {
51   if (!m_elem) {
52     m_elem = gst_bin_new("QtCamViewfinderRendererGenericBin");
53     if (!m_elem) {
54       qCritical() << "Failed to create sink bin";
55       return 0;
56     }
57
58     GstElement *sink = gst_element_factory_make("fakesink", "QtCamViewfinderRendererGenericSink");
59     if (!sink) {
60       qCritical() << "Failed to create fakesink";
61       gst_object_unref(m_elem);
62       m_elem = 0;
63       return 0;
64     }
65
66     g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, "sync", TRUE, NULL);
67     m_id = g_signal_connect(sink, "handoff", G_CALLBACK(on_gst_buffer), this);
68
69     GstElement *csp = gst_element_factory_make("ffmpegcolorspace",
70                                                "QtCamViewfinderRendererGenericCsp");
71     if (!csp) {
72       qCritical() << "Failed to create ffmpegcolorspace";
73       gst_object_unref(sink);
74       gst_object_unref(m_elem);
75       m_elem = 0;
76       return 0;
77     }
78
79     GstElement *filter = gst_element_factory_make("capsfilter",
80                                                   "QtCamViewfinderRendererGenericCapsFilter");
81     if (!filter) {
82       qCritical() << "Failed to create capsfilter";
83       gst_object_unref(sink);
84       gst_object_unref(csp);
85       gst_object_unref(m_elem);
86       m_elem = 0;
87       return 0;
88     }
89
90     GstCaps *caps = gst_caps_from_string(CAPS);
91     g_object_set(filter, "caps", caps, NULL);
92     gst_caps_unref(caps);
93
94     gst_bin_add_many(GST_BIN(m_elem), csp, filter, sink, NULL);
95     gst_element_link_many(csp, filter, sink, NULL);
96
97     GstPad *pad = gst_element_get_static_pad(csp, "sink");
98     gst_element_add_pad(m_elem, gst_ghost_pad_new("sink", pad));
99     gst_object_unref(pad);
100
101     g_object_add_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
102
103     m_sink = sink;
104   }
105
106   return m_elem;
107 }
108
109 void QtCamViewfinderRendererGeneric::on_gst_buffer(GstElement *element,
110                                                    GstBuffer *buf, GstPad *pad,
111                                                    QtCamViewfinderRendererGeneric *q) {
112
113   q->m_mutex.lock();
114
115   if (!q->m_elem) {
116     q->m_mutex.unlock();
117     return;
118   }
119
120   int width, height;
121
122   if (!gst_video_get_size(pad, &width, &height)) {
123     return;
124   }
125
126   QImage image(buf->data, width, height, QImage::Format_RGB32);
127
128   q->m_image = image.copy();
129
130   QMetaObject::invokeMethod(q, "updateRequested", Qt::QueuedConnection);
131
132   q->m_mutex.unlock();
133 }
134
135 void QtCamViewfinderRendererGeneric::sink_notify(QtCamViewfinderRendererGeneric *q,
136                                                  GObject *object,
137                                                  gboolean is_last_ref) {
138
139   if (is_last_ref) {
140     g_object_remove_toggle_ref(G_OBJECT(q->m_elem), (GToggleNotify)sink_notify, q);
141     q->m_elem = 0;
142     q->m_sink = 0;
143   }
144 }