GStreamer的。将appsink写入filesink

时间:2015-01-20 08:39:37

标签: c++ gstreamer

我已经将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; }

3 个答案:

答案 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上关闭它。

希望有所帮助。