c - 从 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, sink, 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。相当浪费,但工作。
推荐阅读
- ruby-on-rails - 用于销毁的语义嵌套形式
- android - TextView 没有与其他视图内联
- c - 我不明白这句话的逻辑“cur = prev->next;” 在 deleteall(key) 函数中
- elasticsearch - 在多字段弹性搜索中设置值
- java - 内部错误:带包的符号文件不能为空
- android - 当另一个设备前台时,我应该停止发送推送通知吗?
- javascript - 正则表达式查找不带引号的 json 值
- android - Firebase 意图不起作用
- postgresql - 通过本地互联网通过 PGAdmin 访问 Postgres Docker DB
- ios - autorelease 对象什么时候释放?