1.回调函数sourceFun
static void cb_need_data(GstElement *appsrc, guint unused_size, gpointer user_data)
{
static int index = 0;
//static GstClockTime timestamp = 0;
GstBuffer *buffer;
guint size;
GstFlowReturn ret;
unsigned char *image = getUsbCameraImage(&size);
if(image == NULL)
{
g_HKCameraStatus.stopPush = true;
}
else
{
buffer = gst_buffer_new_allocate(NULL, size, NULL);
/* cp image to buffer */
gst_buffer_fill(buffer, 0, image, size);
/* Push the buffer into the appsrc */
g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
/* Free the buffer now that we are done with it */
gst_buffer_unref(buffer);
index ++;
}
if(g_HKCameraStatus.stopPush == true)
{
printf("end-of-stream video all frame number = [%d]\n", index);
index = 0;
g_signal_emit_by_name (appsrc, "end-of-stream", NULL);
}
}
2.将摄像头数据流打包为mp4保存在本地
/**
* @brief video to xx.mp4
* @param *source: app
* @param *sink: mp4 file address, example "./sink.mp4"
* @return bool
*/
bool videoEncode_pushToLolcal(void *sourceFun, char *sink, unsigned int outPutWidth, unsigned int outPutHeight, unsigned int bitrate)
{
GstBus *bus;
GstElement *pipeline, *et_source, *et_sink, *et_videoparse, *et_omxh264enc, *et_queue, *et_h264parse, *et_mp4mux, *et_videoconvert;
/* create loop */
GMainLoop *myloop = g_main_loop_new(NULL, FALSE);
/* create pipe */
pipeline = gst_pipeline_new("video-encode");
/* create source-link element */
et_source = gst_element_factory_make("appsrc", "source");
et_sink = gst_element_factory_make("filesink", "file-sink");
/* create videoparse element */
et_videoparse = gst_element_factory_make("videoparse", "work-videoparse");
/* create videoparse element */
et_videoconvert = gst_element_factory_make("videoconvert", "work-videoconvert");
/* create encode element */
et_omxh264enc = gst_element_factory_make("x264enc", "work-omxh264enc");
et_queue = gst_element_factory_make("queue", "work-queue");
et_h264parse = gst_element_factory_make("h264parse", "work-h264parse");
et_mp4mux = gst_element_factory_make("mp4mux", "work-mp4mux");
if(!et_source || !et_sink ||
!et_videoparse ||
!et_videoconvert ||
!et_omxh264enc || !et_queue || !et_h264parse || !et_mp4mux)
{
printf("error One element could not be created\n");
return false;
}
g_object_set(G_OBJECT(et_sink), "location", sink, NULL);
/* set videoparse */
g_object_set(et_videoparse, "format", 4, "width", outPutWidth, "height", outPutHeight, "framerate", "byte-stream", NULL);// "nv12" = 23, yuy2 = 4 ,
/* set videoparse todo*/
g_object_set(et_omxh264enc, "bitrate", bitrate, NULL);
/* get bus */
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_call, myloop);
gst_object_unref(bus);
/* put all elements in a bin */
gst_bin_add_many(GST_BIN(pipeline), et_source, et_videoparse, et_queue, et_videoconvert, et_omxh264enc, et_h264parse, et_mp4mux, et_sink, NULL);
/* link element */
gst_element_link_many(et_source, et_videoparse, et_queue, et_videoconvert, et_omxh264enc, et_h264parse, et_mp4mux, et_sink, NULL);
/* setup appsrc */
g_object_set (G_OBJECT (et_source),
"stream-type", 0,NULL);
g_signal_connect(et_source, "need-data", G_CALLBACK(sourceFun), NULL);
/* Now set to playing and iterate. */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(myloop);
/* clean up nicely */
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return true;
}
3.将摄像头数据流打包为yuv保存在本地
/**
* @brief video to xx.yuv
* @param *source: app
* @param *sink: mp4 file address, example "./sink.yuv"
* @return bool
*/
bool video_pushToLolcal(void *sourceFun, char *sink)
{
GstBus *bus;
GstElement *pipeline, *et_source, *et_sink, *et_queue;
/* create loop */
GMainLoop *myloop = g_main_loop_new(NULL, FALSE);
/* create pipe */
pipeline = gst_pipeline_new("video-encode");
/* create source-link element */
et_source = gst_element_factory_make("appsrc", "source");
et_sink = gst_element_factory_make("filesink", "file-sink");
et_queue = gst_element_factory_make("queue", "work-queue");
if(!et_source || !et_sink || !et_queue)
{
printf("error One element could not be created\n");
return false;
}
g_object_set(G_OBJECT(et_sink), "location", sink, NULL);
/* get bus */
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_call, myloop);
gst_object_unref(bus);
/* put all elements in a bin */
gst_bin_add_many(GST_BIN(pipeline), et_source, et_queue, et_sink, NULL);
/* link element */
gst_element_link_many(et_source, et_queue, et_sink, NULL);
/* setup appsrc */
g_object_set (G_OBJECT (et_source),
"stream-type", 0,NULL);
g_signal_connect(et_source, "need-data", G_CALLBACK(sourceFun), NULL);
/* Now set to playing and iterate. */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(myloop);
/* clean up nicely */
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return true;
}