#include "widget.h" #include "ui_widget.h" ImageStruct Widget::imageStruct= {false, "",NULL}; Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); connect(ui->tb_capture,&QToolButton::clicked,this,&Widget::on_tb_capture_clicked); int rst = init_element(); } Widget::~Widget() { delete ui; } void cvtColorGBRx2RGB(guint8 *dst, guint8 *src, int width, int height) { for (int h = 0; h < height; h++) { for (int w = 0, w1 = 0; w < width*3; w += 3, w1 += 4) { dst[w] = src[w1+2]; dst[w + 1] = src[w1+1]; dst[w + 2] = src[w1]; } dst += width*3; src += width*4; } return; } static GstPadProbeReturn cb_have_data (GstPad *pad, GstPadProbeInfo *info, ImageStruct * date){ if (true == date->image_flag) { g_print("enter cb_have_data\n"); GstBuffer *buffer = nullptr ; GstMapInfo map_info; GstStructure *s; gint width, height; //图片的尺寸 GstCaps *sink_caps =gst_pad_get_current_caps(pad); s = gst_caps_get_structure (sink_caps, 0); gboolean res; res = gst_structure_get_int (s, "width", &width); //获取图片的宽 res |= gst_structure_get_int (s, "height", &height); //获取图片的高 if (!res) { g_print ("gst_structure_get_int fail\n"); return GST_PAD_PROBE_DROP; } // 使用mapinfo获取图像数据 buffer = GST_PAD_PROBE_INFO_BUFFER (info); //info和buffer中的数据不能直接操作 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) { //映射出数据 g_print("gst_buffer_map() error!"); return GST_PAD_PROBE_DROP; } g_print("jpg size = %ld \n", map_info.size); QString strFile = QString("Capture-%0.jpg").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmssz")); guint8 rgb [width*height*3]={0} ; cvtColorGBRx2RGB(rgb, map_info.data, width, height); // QImage保存图片 #if 1 QImage img(rgb, width, height, width * 3, QImage::Format_RGB888); //直接操作映射出的数据map_info img.save(strFile, "jpeg"); #endif //也可以使用GDK的方式保存图片 g_print("save %s succese\n",strFile.toStdString().c_str()); gst_buffer_unmap (buffer, &map_info); date->image_flag = false; GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(date->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "capture"); return GST_PAD_PROBE_OK; } return GST_PAD_PROBE_OK; } int Widget::init_element() { vsrc = gst_element_factory_make ("nvv4l2camerasrc", NULL); gst_util_set_object_arg (G_OBJECT (vsrc), "device","/dev/video0"); vconvert = gst_element_factory_make("nvvidconv","vconvert"); imageTransform = gst_element_factory_make ("nvegltransform", "imagetransform"); playsink = gst_element_factory_make ("nveglglessink", "vsink"); pipeline = gst_pipeline_new ("pipeline"); GstPad *pad = gst_element_get_static_pad (vsrc, "src"); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) cb_have_data, &imageStruct, NULL); gst_object_unref (pad); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (playsink), this->ui->wg_play->winId()); if( !pipeline || !vsrc ||!vconvert || !playsink ||!imageTransform) { g_printerr ("Not all elements could be created.\n"); return -1; } imageStruct.pipeline = pipeline; gst_bin_add_many (GST_BIN (pipeline), vsrc, vconvert, playsink,imageTransform, NULL); if(gst_element_link_many (vsrc, vconvert,imageTransform,playsink, NULL) != TRUE) { g_printerr ("Elements could not be linked.\n"); gst_object_unref (pipeline); return -1; } GstStateChangeReturn sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (sret == GST_STATE_CHANGE_FAILURE) { gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); // Exit application //QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); } } GstPadProbeReturn Widget::cb_have_data (GstPad *pad,GstPadProbeInfo *info,ImageStruct * date){ if (true == date->image_flag) { g_print("enter cb_have_data\n"); GstBuffer *buffer = nullptr ; GstMapInfo map_info; GstStructure *s; gint width, height; //图片的尺寸 GstCaps *sink_caps =gst_pad_get_current_caps(pad); s = gst_caps_get_structure (sink_caps, 0); gboolean res; res = gst_structure_get_int (s, "width", &width); //获取图片的宽 res |= gst_structure_get_int (s, "height", &height); //获取图片的高 if (!res) { g_print ("gst_structure_get_int fail\n"); return GST_PAD_PROBE_DROP; } // 使用mapinfo获取图像数据 buffer = GST_PAD_PROBE_INFO_BUFFER (info); //info和buffer中的数据不能直接操作 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) { //映射出数据 g_print("gst_buffer_map() error!"); return GST_PAD_PROBE_DROP; } g_print("jpg size = %ld \n", map_info.size); QString strFile = QString("Capture-%0.jpg").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmssz")); guint8 rgb [width*height*3]={0} ; cvtColorGBRx2RGB(rgb, map_info.data, width, height); //ignore this // QImage保存图片 #if 1 QImage img(rgb, width, height, width * 3, QImage::Format_RGB888); //直接操作映射出的数据map_info img.save(strFile, "jpeg"); #endif //也可以使用GDK的方式保存图片 g_print("save %s succese\n",strFile.toStdString().c_str()); gst_buffer_unmap (buffer, &map_info); date->image_flag = false; GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(date->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "capture"); return GST_PAD_PROBE_OK; } return GST_PAD_PROBE_OK; } gboolean Widget::postGstMessage(GstBus *bus, GstMessage * message, gpointer user_data) { Widget *pw = NULL; if (user_data) { pw = reinterpret_cast(user_data); } switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_STATE_CHANGED: { GstState old_state, new_state, pending_state; gst_message_parse_state_changed (message, &old_state, &new_state, &pending_state); pw->sigState(new_state); break; } case GST_MESSAGE_TAG: { GstTagList *tags = NULL; gst_message_parse_tag(message, &tags); gchar *album= NULL; if (gst_tag_list_get_string(tags, GST_TAG_ALBUM, &album)) { pw->sigAlbum(album); g_free(album); } gst_tag_list_unref(tags); break; } case GST_MESSAGE_EOS: { pw->sigEos(); break; } default: break; } return TRUE; } void Widget::on_tb_capture_clicked() { this->imageStruct.image_flag = true; }