gpt4 book ai didi

c++ - 更改 GStreamer 上的视频格式

转载 作者:搜寻专家 更新时间:2023-10-31 01:47:30 28 4
gpt4 key购买 nike

我正在尝试为我正在编写的应用程序在 gstreamer-1.0 上覆盖 .png 图像(带有 alpha channel ),但是,在大量搜索网络和阅读文档之后,我仍然对使用方法。

我使用的方法是:

filesrc -> pngdec -> imagefreeze -> videoconvert -> videoscale ->videomixer -> output_of_bininput_of_bin -> videoconvert -> videoscale ->|

这是一个较大应用程序的一小部分。

我的问题是设置 videoscale 和 videoconvert 元素的属性,我认为您应该使用 GSTCaps,但这不起作用。我试过很多方法。这是提供覆盖的类中的成员函数。对于代码的困惑,我深表歉意,但它是实验性的。

bool ImageOverlay::CreateElement()
{
GstPad *source_pad, *sink_pad;
GstElement *file_source, *png_decoder, *freeze, *colorspace,
*video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2;

/* Create gstreamer elements */
_image_overlay_element = gst_bin_new("image-player");

if(!_image_overlay_element)
{
g_printerr ("Pipeline could not be created. Exiting.\n");
return false;
}

// Create file source
file_source = gst_element_factory_make ("multifilesrc", "file-source");
g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL);

if(!file_source)
{
g_printerr ("File could not be created. Exiting.\n");
return false;
}

// Decode file
png_decoder = gst_element_factory_make ("pngdec", "png-decoder");
if(!png_decoder)
{
g_printerr ("png-decoder could not be created. Exiting.\n");
return false;
}

// Create colour space convertor
colorspace = gst_element_factory_make("videoconvert", "colorspace");
if(!colorspace)
{
g_printerr ("Colorspace could not be created. Exiting.\n");
return false;
}

// Create colour space convertor
colorspace2 = gst_element_factory_make("videoconvert", "colorspace2");
if(!colorspace)
{
g_printerr ("Colorspace could not be created. Exiting.\n");
return false;
}

// Create idenentiy component, does nothing but is useful for debug
identity = gst_element_factory_make("identity", "identity");
if(!identity)
{
g_printerr ("Colorspace could not be created. Exiting.\n");
return false;
}

// Create a video mixer
video_mixer = gst_element_factory_make("videomixer", "mixer");
if(!video_mixer)
{
g_printerr ("videomixer could not be created. Exiting.\n");
return false;
}

// Create a freeze element
freeze = gst_element_factory_make("imagefreeze", "freeze");
if(!freeze)
{
g_printerr ("ImageFreeze could not be created. Exiting.\n");
return false;
}

video_scale_1 = gst_element_factory_make("videoscale", NULL);
if(!video_scale_1)
{
g_printerr ("video_scale_1 could not be created. Exiting.\n");
return false;
}

video_scale_2 = gst_element_factory_make("videoscale", NULL);
if(!video_scale_2)
{
g_printerr ("video_scale_2 could not be created. Exiting.\n");
return false;
}

// Add to the bin
gst_bin_add_many (GST_BIN (_image_overlay_element),
file_source,
png_decoder,
colorspace,
colorspace2,
freeze,
video_mixer,
identity,
video_scale_1,
video_scale_2,
NULL);


if (!gst_element_link_many (file_source, png_decoder, video_scale_1, freeze, NULL))
{
std::cout << "Could not link" << std::endl;
}

GstCaps * caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "ARGB",
NULL);


GstCaps * caps2 = gst_caps_new_simple("width", G_TYPE_INT, 640,
"height", G_TYPE_INT, 480,
NULL);

gst_element_link_filtered(video_scale_1, freeze, caps2);
gst_element_link_filtered(video_scale_2, freeze, caps2);

if (!gst_element_link_many(freeze, video_scale_2, colorspace, NULL))
{
std::cout << "Could not link" << std::endl;
}

// Link pads to video mixer
GstPad * sink_pad_1 = gst_element_get_request_pad (video_mixer, "sink_%u");
GstPad * sink_pad_2 = gst_element_get_request_pad (video_mixer, "sink_%u");
GstPad * source_2 = gst_element_get_static_pad (identity, "src");
GstPad * source_1 = gst_element_get_static_pad (colorspace, "src");

gst_pad_set_caps(source_2, caps);
gst_pad_set_caps(source_1, caps);
gst_caps_unref(caps);

if (!gst_pad_link ( source_1, sink_pad_1) == GST_PAD_LINK_OK)
{
std::cout << "Could not link pads" << std::endl;
return false;
}

if (!gst_pad_link ( source_2, sink_pad_2) == GST_PAD_LINK_OK)
{
std::cout << "Could not link pads" << std::endl;
return false;
}

gst_pad_set_active(source_1, true);
gst_pad_set_active(sink_pad_1, true);
gst_pad_set_active(source_2, true);
gst_pad_set_active(sink_pad_2, true);

// Add pad to this element
source_pad = gst_element_get_static_pad (video_mixer, "src");
sink_pad = gst_element_get_static_pad(identity, "sink");
gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("src", source_pad));
gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("sink", sink_pad));

return true;
}

我想将两个源调整为相同大小,并将 png 图像覆盖在视频上。该 block 主要起作用,但我无法使调整大小或 alpha channel 的东西起作用。

谢谢,

编辑:

我现在已经修改了我的代码并且有了更好的理解,但是,问题似乎在于,如果 capfilter 使用 RGBA,则它不会链接,其他一些格式可以工作但没有用。我不知道为什么。

bool ImageOverlay::MakeElements()
{
try
{
// Creates the bin at this level
CreatePipeline();
GstElement *file_source, *png_decoder, *freeze, *colorspace,
*video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2, *caps_filter1, *caps_filter2;

// Create elements
file_source = CreateElementAndAddToBin("multifilesrc", "file-source");
png_decoder = CreateElementAndAddToBin("pngdec", "png-decoder");
colorspace = CreateElementAndAddToBin("videoconvert", "colorspace");
colorspace2 = CreateElementAndAddToBin("videoconvert", "colorspace2");
identity = CreateElementAndAddToBin("identity", "identity");
video_mixer = CreateElementAndAddToBin("videomixer", "mixer");
freeze = CreateElementAndAddToBin("imagefreeze", "freeze");
video_scale_1 = CreateElementAndAddToBin("videoscale", "scale1");
video_scale_2 = CreateElementAndAddToBin("videoscale", "scale2");
caps_filter1 = CreateElementAndAddToBin("capsfilter", "caps_filter1");
caps_filter2 = CreateElementAndAddToBin("capsfilter", "caps_filter2");

// Set input file
g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL);

// Create caps
GstCaps *caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "YV12", //<<< IF THIS IS SET TO ARGB (THE FORMAT I WANT IT FAILS ON LINKING)
"framerate", GST_TYPE_FRACTION, 25, 1,
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
"width", G_TYPE_INT, 640,
"height", G_TYPE_INT, 480,
NULL);


// Set caps on cap filter
g_object_set(G_OBJECT(caps_filter2), "caps", caps, NULL);
g_object_set(G_OBJECT(caps_filter1), "caps", caps, NULL);


// Link up elements
if (!gst_element_link_many (identity, video_scale_2, colorspace2, caps_filter2, video_mixer, NULL))
{
std::cout << "Could not link input branch" << std::endl; //<<<< IF ARGB OR OTHER FORMATS SUCH AS RGBA ARE USED
} // IN CAP FILTER, THIS FAILS, SAME WITH BELOW. IT WORKS WITH YV12!

if (!gst_element_link_many (file_source, png_decoder, freeze, video_scale_1, colorspace, caps_filter1, video_mixer, NULL))
{
std::cout << "Could not link image source branch" << std::endl;
}

// Add ghost pads to this bin, allowing it to be used as an element
SetInputElement(identity);
SetOutputElement(video_mixer);
}
catch(...)
{
std::cout << "Overlay generator failed to build, exception thrown" << std::endl;

// TODO - Clear up in here
return false;
}

return true;
}

最佳答案

从 gstreamer 1.2 开始,视频转换由混音器承担,如果其中一个接收器垫具有 alpha,它将自动选择一种 alpha 格式。

如果您可以更新到 1.2,您需要使用的管道将具有以下形式:

gst-launch-1.0 uridecodebin uri=file:///home/meh/Pictures/pitivi/nicetext.png ! imagefreeze ! videomixer name=m sink_0::zorder=0 ! videoconvert ! autovideosink videotestsrc ! videoscale ! video/x-raw, width=640, height=400 ! m.

其中 nicetext.png 是一个 (png) 640 x 400 图像文件,具有透明背景和一些随机文本。

videoscale 之后的部分是一个 capsfilter,你可以通过以下方式创建它:

gst_element_factory_make("capsfilter", "random_name")

然后将其 caps 属性设置为您需要的宽度和高度。如果事先不知道这一点,您将需要在焊盘上设置一个焊盘探针,您需要从中复制宽度和高度、拦截 caps 事件并在此时将 caps 设置在 capsfilter 上。

如果由于某种原因您不能使用 1.2,那么您将需要在两个分支上使用 videoconvert 和 capsfilter,并指定您需要的格式。

关于c++ - 更改 GStreamer 上的视频格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19139162/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com