-
Notifications
You must be signed in to change notification settings - Fork 3
/
scannerqwidgetsink.cpp
151 lines (129 loc) · 4.15 KB
/
scannerqwidgetsink.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "scannerqwidgetsink.h"
#include <QDebug>
uint ScannerQWidgetSink::CAPTURE_HEIGHT = 480;
uint ScannerQWidgetSink::CAPTURE_WIDTH = 640;
ScannerQWidgetSink::ScannerQWidgetSink(ViewfinderWidget *sinkWidget, QString vidSrc):
bRendering(false),
bExiting(false),
pipeline(NULL),
sem(0)
{
widget2Sink = sinkWidget;
GstPipelineInit(vidSrc);
}
ScannerQWidgetSink::~ScannerQWidgetSink()
{
if (bRendering)
StopRender();
if (!bExiting)
ExitRender();
if (pipeline)
GstPipelineUnInit();
delete renderTimer;
}
bool ScannerQWidgetSink::GstPipelineInit(QString source)
{
// init the gstreamer
gst_init(NULL, NULL);
// create pipeline from parser
GError *error = NULL;
QString resolution;
resolution.sprintf("width=%d,height=%d",
ScannerQWidgetSink::CAPTURE_WIDTH,
ScannerQWidgetSink::CAPTURE_HEIGHT);
QString launchCmd = source +
" ! video/x-raw,format=YUY2,framerate=20/1," + resolution +
#ifdef LINUX_HOST
" ! videoconvert"
#else
" ! imxvideoconvert_pxp"
#endif
" ! video/x-raw,format=RGB16 ! appsink name=\"mysink\"";
pipeline = gst_parse_launch(launchCmd.toLocal8Bit().constData(), &error);
if (!pipeline) {
qDebug() << "Failed to create pipeline:" << launchCmd.toLocal8Bit().constData();
return false;
}
// get appsink
mysink = gst_bin_get_by_name(GST_BIN(pipeline), "mysink");
g_signal_connect(pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify), NULL);
gst_app_sink_set_emit_signals((GstAppSink *)mysink, true);
gst_app_sink_set_drop((GstAppSink *)mysink, true);
gst_app_sink_set_max_buffers((GstAppSink *)mysink, 1);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
bus = gst_element_get_bus(pipeline);
// init the buffer size for QImage
// RGB565 takes 2Bytes per pixel
int imgSize = ScannerQWidgetSink::CAPTURE_HEIGHT *
ScannerQWidgetSink::CAPTURE_WIDTH * 2;
imgBuffer.resize(imgSize);
widget2Sink->LoadImageBuffer(imgBuffer,
ScannerQWidgetSink::CAPTURE_WIDTH,
ScannerQWidgetSink::CAPTURE_HEIGHT);
renderTimer = new QTimer(this);
connect(renderTimer, SIGNAL(timeout()), this, SLOT(Rendering()));
return true;
}
void ScannerQWidgetSink::GstPipelineUnInit()
{
if (pipeline) {
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(mysink);
gst_object_unref(pipeline);
gst_object_unref(bus);
pipeline = NULL;
}
}
void ScannerQWidgetSink::StartRender()
{
renderTimer->start(50);
bRendering = true;
}
void ScannerQWidgetSink::StopRender()
{
bRendering = false;
renderTimer->stop();
}
void ScannerQWidgetSink::ExitRender()
{
bExiting = true;
sem.release(3);
}
void ScannerQWidgetSink::CopyFrameData(QByteArray &dest)
{
memcpy(dest.data(), imgBuffer.constData(), imgBuffer.size());
}
bool ScannerQWidgetSink::WaitForFrameData()
{
sem.acquire(1);
if (bExiting)
return false;
return true;
}
void ScannerQWidgetSink::Rendering()
{
if(!pipeline || !bRendering)
return;
static int renderCnt = 0;
// polling
GstSample *sample = gst_app_sink_pull_sample((GstAppSink *)mysink);
// get RGB565 buffer
GstBuffer *gstImageBuffer = gst_sample_get_buffer(sample);
GstCaps *cap = gst_sample_get_caps(sample);
const GstStructure *str = gst_caps_get_structure (cap, 0);
gint width, height;
if (!gst_structure_get_int (str, "width", &width) ||
!gst_structure_get_int (str, "height", &height)) {
qDebug() << "can not get WxH in the caps";
} else {
gst_buffer_extract(gstImageBuffer, 0, imgBuffer.data(), imgBuffer.size());
widget2Sink->update();
// release semaphore for decoder thread access buffer
if (renderCnt ++ >= 10) {
renderCnt = 0;
sem.release(1);
}
}
//gst_buffer_unref(gstImageBuffer);
gst_sample_unref(sample);
}