我已经将appsrc的代码写入了appsink,但它确实有用。我看到了实际的缓冲区。它在H264中编码(vpuenc = avc)。现在我想将它保存在一个文件(filesink)中。我怎么接近它?
应用程式:
int main(int argc, char *argv[]) {
gst_init (NULL, NULL);
GstElement *pipeline, *sink;
gchar *descr;
GError *error = NULL;
GstAppSink *appsink;
descr = g_strdup_printf (
"mfw_v4lsrc device=/dev/video1 capture_mode=0 ! " // grab from mipi camera
"ffmpegcolorspace ! vpuenc codec=avc ! "
"appsink name=sink"
);
pipeline = gst_parse_launch (descr, &error);
if (error != NULL) {
g_print ("could not construct pipeline: %s\n", error->message);
g_error_free (error);
exit (-1);
}
gst_element_set_state(pipeline, GST_STATE_PAUSED);
sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
appsink = (GstAppSink *) sink;
gst_app_sink_set_max_buffers ( appsink, 2); // limit number of buffers queued
gst_app_sink_set_drop( appsink, true ); // drop old buffers in queue when full
gst_element_set_state (pipeline, GST_STATE_PLAYING);
int i = 0;
while( !gst_app_sink_is_eos(appsink) )
{
GstBuffer *buffer = gst_app_sink_pull_buffer(appsink);
uint8_t* data = (uint8_t*)GST_BUFFER_DATA(buffer);
uint32_t size = GST_BUFFER_SIZE(buffer);
gst_buffer_unref(buffer);
}
return 0; }
答案 0 :(得分:1)
在这种情况下,你不要编写自己的while循环。注册回调并等待缓冲区(GStreamer 0.10)到达。如果您正在使用GStreamer 1.0,则使用样本而不是缓冲区。与缓冲液相比,样品在屁股上是一个巨大的痛苦,但很好。
注册回调:
GstAppSinkCallbacks* appsink_callbacks = (GstAppSinkCallbacks*)malloc(sizeof(GstAppSinkCallbacks));
appsink_callbacks->eos = NULL;
appsink_callbacks->new_preroll = NULL;
appsink_callbacks->new_sample = app_sink_new_sample;
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), appsink_callbacks, (gpointer)pointer_to_data_passed_to_the_callback, free);
你的回调:
GstFlowReturn app_sink_new_sample(GstAppSink *sink, gpointer user_data) {
prog_data* pd = (prog_data*)user_data;
GstSample* sample = gst_app_sink_pull_sample(sink);
if(sample == NULL) {
return GST_FLOW_ERROR;
}
GstBuffer* buffer = gst_sample_get_buffer(src);
GstMemory* memory = gst_buffer_get_all_memory(buffer);
GstMapInfo map_info;
if(! gst_memory_map(memory, &map_info, GST_MAP_READ)) {
gst_memory_unref(memory);
gst_sample_unref(sample);
return GST_FLOW_ERROR;
}
//render using map_info.data
gst_memory_unmap(memory, &map_info);
gst_memory_unref(memory);
gst_sample_unref(sample);
return GST_FLOW_OK;
}
你可以保持你的while循环 - 使用gst_app_sink_is_eos() - 但确保在其中放入一个睡眠。大多数时候我会使用以下内容:
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
注意:除非你需要对数据做些特别的事情,否则你可以使用" filesink"元素直接。
答案 1 :(得分:1)
如果你在评论中提到过,你真正想知道的是如何在GStreamer中进行网络视频流,你可能应该关闭这个问题,因为你走错了路。您不需要使用appsink或filesink。您想要研究的是与RTP,RTSP,RTMP,MPEGTS甚至MJPEG相关的GStreamer元素(如果您的图像尺寸足够小)。
以下是两个基本的发送/接收视频流管道:
gst-launch-0.10 v4l2src! ffmpegcolorspace!视频! video / x-raw-yuv,width = 640,height = 480! vpuenc! h264parse! rtph264pay! udpsink host = localhost port = 5555
gst-launch-0.10 udpsrc port = 5555! application / x-rtp,encoding-name = H264,payload = 96! rtph264depay! h264parse! ffdec_h264!视频转换! ximagesink
答案 2 :(得分:0)
更简单的选项是直接在appsink本身写入文件,即当缓冲区完成后收到回调时,写入文件并确保在eos上关闭它。
希望有所帮助。