1 #include "qtcamviewfinderrenderergeneric.h"
3 #include <gst/video/video.h>
5 #include "qtcamconfig.h"
7 QT_CAM_VIEWFINDER_RENDERER(RENDERER_TYPE_GENERIC, QtCamViewfinderRendererGeneric);
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"
11 // TODO: this needs to be debugged or rewritten. There are race conditions.
12 QtCamViewfinderRendererGeneric::QtCamViewfinderRendererGeneric(QtCamConfig *config,
14 QtCamViewfinderRenderer(config, parent), m_elem(0), m_sink(0), m_id(0) {
18 QtCamViewfinderRendererGeneric::~QtCamViewfinderRendererGeneric() {
22 g_object_remove_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
25 g_signal_handler_disconnect(m_sink, m_id);
31 void QtCamViewfinderRendererGeneric::paint(QPainter *painter) {
32 // TODO: scale and keep aspect ratio.
35 if (!m_image.isNull()) {
36 painter->drawImage(QRectF(QPointF(0, 0), m_size), m_image);
42 void QtCamViewfinderRendererGeneric::resize(const QSizeF& size) {
46 void QtCamViewfinderRendererGeneric::reset() {
50 GstElement *QtCamViewfinderRendererGeneric::sinkElement() {
52 m_elem = gst_bin_new("QtCamViewfinderRendererGenericBin");
54 qCritical() << "Failed to create sink bin";
58 GstElement *sink = gst_element_factory_make("fakesink", "QtCamViewfinderRendererGenericSink");
60 qCritical() << "Failed to create fakesink";
61 gst_object_unref(m_elem);
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);
69 GstElement *csp = gst_element_factory_make("ffmpegcolorspace",
70 "QtCamViewfinderRendererGenericCsp");
72 qCritical() << "Failed to create ffmpegcolorspace";
73 gst_object_unref(sink);
74 gst_object_unref(m_elem);
79 GstElement *filter = gst_element_factory_make("capsfilter",
80 "QtCamViewfinderRendererGenericCapsFilter");
82 qCritical() << "Failed to create capsfilter";
83 gst_object_unref(sink);
84 gst_object_unref(csp);
85 gst_object_unref(m_elem);
90 GstCaps *caps = gst_caps_from_string(CAPS);
91 g_object_set(filter, "caps", caps, NULL);
94 gst_bin_add_many(GST_BIN(m_elem), csp, filter, sink, NULL);
95 gst_element_link_many(csp, filter, sink, NULL);
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);
101 g_object_add_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
109 void QtCamViewfinderRendererGeneric::on_gst_buffer(GstElement *element,
110 GstBuffer *buf, GstPad *pad,
111 QtCamViewfinderRendererGeneric *q) {
122 if (!gst_video_get_size(pad, &width, &height)) {
126 QImage image(buf->data, width, height, QImage::Format_RGB32);
128 q->m_image = image.copy();
130 QMetaObject::invokeMethod(q, "updateRequested", Qt::QueuedConnection);
135 void QtCamViewfinderRendererGeneric::sink_notify(QtCamViewfinderRendererGeneric *q,
137 gboolean is_last_ref) {
140 g_object_remove_toggle_ref(G_OBJECT(q->m_elem), (GToggleNotify)sink_notify, q);