appsrc也支持push模式。
简单来说,就是你主动地把数据“填充”或者说是“发送”到appsrc里面。例如你自己创建一个thread,每间隔3秒往appsrc里面填充一次数据。我看了网上的一些demo,基本上都是通过pull模式的callback来做的, push模式相关的demo也比较不好找。
这种场景,我举个例子,比如你用ffmpeg获取到了一些h264的帧数据,想要自己主动地push到appsrc里面。
在上篇文章里的代码基础上做一些改动,核心就是填充数据以后,调用一下g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret); 上篇文章里的pull模式里的 // g_signal_connect (appsrc, "need-data", G_CALLBACK (cb_need_data), NULL); 可以放心注释掉了
还有另外一个API:gst_app_src_push_buffer,区别在于buffer的owner关系,具体可以查看官方API文档。
g_signal_emit_by_name() does not take ownership of the buffer (meaning: you have to unref it afterwards), while gst_app_src_push_buffer() does.
// 启动一个线程来调用,写的有点随意,仅当demo用
void* doWork(void *userdata) {
while (TRUE) {
printf("dowork ===! \n");
static gboolean white = FALSE;
static GstClockTime timestamp = 0;
GstBuffer *buffer;
guint size;
GstFlowReturn ret;
size = VIDEO_WIDTH * VIDEO_HEIGHT * PIXEL_SIZE;
buffer = gst_buffer_new_allocate(NULL, size, NULL);
/* this makes the image black/white */
gst_buffer_memset(buffer, 0, white ? 0xFF : 0x00, size);
white = !white;
GST_BUFFER_PTS (buffer) = timestamp;
// 需要注意一下时间戳
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int(3, GST_SECOND,
1);
timestamp += GST_BUFFER_DURATION(buffer);
g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref(buffer);
if (ret != GST_FLOW_OK) {
g_printf("ret not ok! \n");
/* something wrong, stop pushing */
// g_main_loop_quit (loop);
} else {
g_printf("ret ok! \n");
}
// 测试每次间隔3秒填充一次
g_usleep(3000000);
}
}
Start a thread and from that thread push buffers to appsrc as fast as possible.
Enjoy it !