我尝试将gstreamer c代码与ZXing-cpp集成https://github.com/nu-book/zxing-cpp.
这是我的代码
#include "core/ReadBarcode.h"
#include "core/TextUtfEncoding.h"
#include <algorithm>
#include <cctype>
#include <cstring>
#include <iostream>
#include <string>
#include <deque>
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <stdlib.h>
using namespace ZXing;
std::deque<ImageView> frameQueue;
GstFlowReturn
new_preroll(GstAppSink *appsink, gpointer data) {
g_print ("Got preroll!n");
return GST_FLOW_OK;
}
GstFlowReturn
new_sample(GstAppSink *appsink, gpointer data) {
static int framecount = 0;
framecount++;
GstSample *sample = gst_app_sink_pull_sample(appsink);
GstCaps *caps = gst_sample_get_caps(sample);
GstBuffer *buffer = gst_sample_get_buffer(sample);
const GstStructure *info = gst_sample_get_info(sample);
// ---- Read frame and convert to ImageView format ---------------
GstMapInfo map;
gst_buffer_map (buffer, &map, GST_MAP_READ);
g_print("Processing new data n");
ImageView frame( (unsigned char *)map.data, 720, 480,ImageFormat::RGBX);
frameQueue.push_back(frame);
gst_buffer_unmap(buffer, &map);
// ------------------------------------------------------------
// show caps on first frame
if (framecount == 1) {
g_print ("%sn", gst_caps_to_string(caps));
}
gst_sample_unref (sample);
return GST_FLOW_OK;
}
static gboolean
my_bus_callback (GstBus *bus, GstMessage *message, gpointer data) {
g_print ("Got %s messagen", GST_MESSAGE_TYPE_NAME (message));
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR: {
GError *err;
gchar *debug;
gst_message_parse_error (message, &err, &debug);
g_print ("Error: %sn", err->message);
g_error_free (err);
g_free (debug);
break;
}
case GST_MESSAGE_EOS:
g_print ("End of Stream n ");
// end-of-stream
break;
case GST_MESSAGE_STATE_CHANGED:
// state has changed
break;
default:
// unhandled message
g_print ("Unknown Error n ");
break;
}
/* we want to be notified again the next time there is a message
* on the bus, so returning TRUE (FALSE means we want to stop watching
* for messages on the bus and our callback should not be called again)
*/
return TRUE;
}
int main (int argc, char *argv[])
{
GError *error = NULL;
gst_init (&argc, &argv);
gchar *descr = g_strdup(
"v4l2src ! "
"videorate ! "
"video/x-raw,width=720,height=480 ! "
"tee name=qr "
"qr. ! queue ! "
"timeoverlay ! "
"autovideosink "
"qr. ! queue ! "
"appsink name=qrsink sync=true "
);
g_print("launching pipeline n");
GstElement *pipeline = gst_parse_launch (descr, &error);
if (error != NULL) {
g_print ("could not construct pipeline: %sn", error->message);
g_error_free (error);
exit (-1);
}
/* get sink */
GstElement *sink = gst_bin_get_by_name (GST_BIN (pipeline), "qrsink");
gst_app_sink_set_emit_signals((GstAppSink*)sink, true);
gst_app_sink_set_drop((GstAppSink*)sink, true);
gst_app_sink_set_max_buffers((GstAppSink*)sink, 1);
GstAppSinkCallbacks callbacks = { NULL, new_preroll, new_sample };
gst_app_sink_set_callbacks (GST_APP_SINK(sink), &callbacks, NULL, NULL);
GstBus *bus;
guint bus_watch_id;
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL);
gst_object_unref (bus);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
while(1) {
// g_main_iteration(false);
g_main_context_iteration(NULL, false);
DecodeHints hints;
bool haveResult;
if (frameQueue.size() > 0) {
g_print("Outputting image n");
ImageView subject = frameQueue.front();
g_print("Begin Image Processing n");
auto result = ReadBarcode(subject, hints);
}
}
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
现在我面临以下错误
Segmentation fault: (Core dumped)
我已经把错误缩小到这一行
auto result = ReadBarcode(subject, hints);
不知何故,不允许对图像对象(主题为objectType ImageView,其定义可以在ZXing-cpp github站点ReadBarCode.h/cpp中找到(进行内存访问。我想知道出了什么问题。
或者想知道错误可能是将gstreamer缓冲区分配给队列
ImageView frame( (unsigned char *)map.data, 720, 480,ImageFormat::RGBX);
frameQueue.push_back(frame);
感谢您的帮助
对代码进行了以下更改。我没有使用ImageView(它原来是对象的视图,而不是内存(,而是改用std::array<无符号字符,memory_size>帧作为缓冲区的持有者,并使用它进入队列
std::array<unsigned char, FRAME_HEIGHT * FRAME_WIDTH> frame;
std::memcpy (frame.data(), buf, FRAME_HEIGHT * FRAME_WIDTH);
frameQueue.push_back(frame);
在另一个尺寸上,我得到了队列的前面
auto result = ReadBarcode( { (frameQueue.front()).data(), FRAME_WIDTH, FRAME_HEIGHT, ImageFormat::Lum}, hints);
并且当操作在上时
frameQueue.pop_front((
这个实现有什么问题吗?
问候