微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 Gstreamer appsinnk 保存 jpeg 的最佳方法

如何解决从 Gstreamer appsinnk 保存 jpeg 的最佳方法

我有一个 USB 摄像头生成 MJPEG 流,我正在通过我的应用程序读取它。我想保存图像(JPEG)。我试图通过创建从应用程序到图像的第二条管道来实现这一点,但我是第一个承认我不知道如何正确终止这样一条管道的人。该实现在平均拍摄 3 张图像后使应用程序崩溃。 如果可能,我不希望对图像进行重新解码。与创建第二个管道/解码图像相比,有没有其他方法可以保存图像?

我目前的实现是:

static GstFlowReturn new_sample_jpeg(GstElement * elt,MyStruct *data){

    GstSample *sample;
    GstBuffer *buffer;
    GstMemory *memory;
    GstMapInfo info;
    GstFlowReturn ret = GST_FLOW_OK;
    // get the sample from appsink
    sample = gst_app_sink_pull_sample (GST_APP_SINK (elt));
    //if recording,send the sample to recording sink
    if (data->saveVideo) addSampleFromAppsinkVideo(gst_sample_copy(sample));
    buffer = gst_sample_get_buffer (sample);

    if (buffer != NULL){
 memory = gst_buffer_get_memory (buffer,0);

    if (memory != NULL) {
        //Now all data are image data. If image wanted->image save!
        if (data->saveImage) saveSampleFromAppsinkJpeg(gst_sample_copy(sample));
        ...

        gst_memory_unref(memory);
    } else {
        std::cerr << "sample_from_sink(): ERROR memory" << std::endl;
    }
} else {
    std::cerr << "sample_from_sink(): ERROR buffer " << gst_buffer_get_size(buffer) << std::endl;
}
gst_sample_unref (sample);
return ret;
}



int saveSampleFromAppsinkJpeg( GstSample *sample){

//create the pipeline
GstStateChangeReturn ret;

GstElemenent *source = gst_element_factory_make ("appsrc","appsrc_capture");
GstElemenent *sink = gst_element_factory_make ("multifilesink","sink_capture");

g_object_set (sink,"location","some/path.jpg",NULL);

GstElemenent *pipeline = gst_pipeline_new ("pipeline_img");

if (!pipeline || !source || !sink) {
  g_printerr ("Not all elements Could be created.\n");
  return false;
}

GstCaps *caps;
caps = gst_sample_get_caps(sample);

gst_app_src_set_caps(GST_APP_SRC(source),caps);
gst_app_src_set_duration(GST_APP_SRC(source),GST_TIME_AS_MSECONDS(80));
gst_app_src_set_stream_type(GST_APP_SRC(source),GST_APP_STREAM_TYPE_STREAM);
gst_app_src_set_latency(GST_APP_SRC(source),-1,0);

gst_bin_add_many (GST_BIN (pipeline),source,sink,NULL);
gst_caps_unref (caps);
if (gst_element_link_many(source,NULL) != TRUE) {
  g_printerr ("Elements Could not be linked.\n");
  gst_object_unref (pipeline);
return -1;
}

ret = gst_element_set_state (pipeline,GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
  g_printerr ("Unable to set the pipeline to the playing state.\n");
  gst_object_unref (pipeline);
  return -1;
}

//push the image in the pipeline
GstFlowReturn status = GstFlowReturn::GST_FLOW_OK;
status = gst_app_src_push_sample(GST_APP_SRC(source),sample);
if (status !=  GstFlowReturn::GST_FLOW_OK) g_printerr ("Sample for saving image not pushed: code %d.\n",status);
usleep(500000); // not clean. But how to do this better?
status = gst_app_src_end_of_stream(GST_APP_SRC(source));
if (status !=  GstFlowReturn::GST_FLOW_OK) g_printerr ("EOS for saving image not pushed %d \n",status);
usleep(500000); // not clean. But how to do this better?

//end the pipeline
GstMessage *EndMessage = gst_message_new_eos(&pipeline->object);
gst_bus_post(pipeline->bus,EndMessage);
gst_element_send_event(pipeline,gst_event_new_eos());

/* Free resources */
if (EndMessage != NULL) gst_message_unref (EndMessage);
status = gst_app_src_end_of_stream(GST_APP_SRC(source));

//end the pipeline
usleep(500000); // not clean. But how to do this better?
gst_element_set_state (pipeline,GST_STATE_NULL);
GstState currentState = GST_STATE_READY;
GstClockTime timeout = 50;
uint8_t safetyCounter = 255;
do{
    gst_element_get_state(pipeline,&currentState,NULL,timeout );
    if (safetyCounter-- == 0){ //ok,something is seqIoUsly broken here
        break;
    }
    usleep(10000);
} while (currentState != GST_STATE_NULL);

gst_object_unref (pipeline);
gst_sample_unref(sample);
return 1;

}

解决方法

所以最后我只是使用 uvc 库(https://github.com/libuvc/libuvc)将 mjpeg 解码成 rgb,然后我用 jpeglib 将其编码为 jpeg。很浪费,但有效。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。