如何解决从 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,¤tState,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 举报,一经查实,本站将立刻删除。