使用 Gstreamer 进行文本渲染(appsrc、textrender)
Text rendering with Gstreamer (appsrc, textrender)
我正在尝试使用 GStreamer 呈现文本。文本是我想为视频源的每一帧更新的时间戳。然后时间戳将覆盖在从 v4l2src 捕获的视频流上。
问题是显示输出中只显示第一个时间戳。管道继续 运行,调用 pad 探针并将数据推送到 appsrc。
我在调试输出中看不到任何错误 (GST_DEBUG=4)。
请注意,我不想使用 timeoverlay 或 clockoverlay 插件,因为我将使用我的 SoC 上可用的硬件加速插件来进行覆盖。
我只想生成一个带有文本的视频流,然后我可以将其通过管道传输到我的覆盖插件中。
这些是测试应用程序中的管道:
auto src_pipe = gst_parse_launch("videotestsrc ! video/x-raw,width=1920,height=1080,format=YUY2 ! fakesink name=camera");
auto time_pipe = gst_parse_launch("appsrc name=time_overlay format=3 is-live=true do-timestamp=true ! text/x-raw,format=utf8 ! textrender ! video/x-raw,format=ARGB,framerate=30/1,width=720,height=480 ! autovideoconvert ! autovideosink");
并且我使用以下焊盘探针生成文本:
auto src = gst_bin_get_by_name(GST_BIN(src_pipe), "camera");
auto time_appsrc = gst_bin_get_by_name(GST_BIN(time_pipe), "time_overlay");
auto pad = gst_element_get_static_pad (src, "sink");
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) cb_have_data, time_appsrc, NULL);
gst_object_unref (pad);
static void push_time(GstElement *time_appsrc)
{
GstFlowReturn ret;
GstMapInfo map;
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
static std::string time;
time = "The time " + std::to_string(tp.tv_sec) + "sec " + std::to_string(tp.tv_nsec) + "ns";
auto buffer = gst_buffer_new_and_alloc (time.size());
GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
memcpy(map.data, time.c_str(), time.size());
gst_buffer_unmap (buffer, &map);
g_signal_emit_by_name (time_appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref (buffer);
}
static GstPadProbeReturn cb_have_data (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
{
GstMapInfo map;
GstBuffer *buffer;
GstElement *time_appsrc = (GstElement *)user_data;
buffer = GST_PAD_PROBE_INFO_BUFFER (info);
push_time(time_appsrc);
GST_PAD_PROBE_INFO_DATA (info) = buffer;
return GST_PAD_PROBE_OK;
}
找到问题了。我将缓冲区的时间戳设置为固定值...删除下面的行使其按预期工作。
GST_BUFFER_TIMESTAMP (缓冲区) = gst_util_uint64_scale (1, GST_SECOND, 25);
我正在尝试使用 GStreamer 呈现文本。文本是我想为视频源的每一帧更新的时间戳。然后时间戳将覆盖在从 v4l2src 捕获的视频流上。
问题是显示输出中只显示第一个时间戳。管道继续 运行,调用 pad 探针并将数据推送到 appsrc。 我在调试输出中看不到任何错误 (GST_DEBUG=4)。
请注意,我不想使用 timeoverlay 或 clockoverlay 插件,因为我将使用我的 SoC 上可用的硬件加速插件来进行覆盖。 我只想生成一个带有文本的视频流,然后我可以将其通过管道传输到我的覆盖插件中。
这些是测试应用程序中的管道:
auto src_pipe = gst_parse_launch("videotestsrc ! video/x-raw,width=1920,height=1080,format=YUY2 ! fakesink name=camera");
auto time_pipe = gst_parse_launch("appsrc name=time_overlay format=3 is-live=true do-timestamp=true ! text/x-raw,format=utf8 ! textrender ! video/x-raw,format=ARGB,framerate=30/1,width=720,height=480 ! autovideoconvert ! autovideosink");
并且我使用以下焊盘探针生成文本:
auto src = gst_bin_get_by_name(GST_BIN(src_pipe), "camera");
auto time_appsrc = gst_bin_get_by_name(GST_BIN(time_pipe), "time_overlay");
auto pad = gst_element_get_static_pad (src, "sink");
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) cb_have_data, time_appsrc, NULL);
gst_object_unref (pad);
static void push_time(GstElement *time_appsrc)
{
GstFlowReturn ret;
GstMapInfo map;
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
static std::string time;
time = "The time " + std::to_string(tp.tv_sec) + "sec " + std::to_string(tp.tv_nsec) + "ns";
auto buffer = gst_buffer_new_and_alloc (time.size());
GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
memcpy(map.data, time.c_str(), time.size());
gst_buffer_unmap (buffer, &map);
g_signal_emit_by_name (time_appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref (buffer);
}
static GstPadProbeReturn cb_have_data (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
{
GstMapInfo map;
GstBuffer *buffer;
GstElement *time_appsrc = (GstElement *)user_data;
buffer = GST_PAD_PROBE_INFO_BUFFER (info);
push_time(time_appsrc);
GST_PAD_PROBE_INFO_DATA (info) = buffer;
return GST_PAD_PROBE_OK;
}
找到问题了。我将缓冲区的时间戳设置为固定值...删除下面的行使其按预期工作。
GST_BUFFER_TIMESTAMP (缓冲区) = gst_util_uint64_scale (1, GST_SECOND, 25);