gpt4 book ai didi

Haskell GStreamer tee element(1-N) 麻烦

转载 作者:行者123 更新时间:2023-12-02 13:16:50 26 4
gpt4 key购买 nike

我遇到的问题与以下代码有关:

module Main(main) where

import qualified Media.Streaming.GStreamer as GS
import Data.Maybe
import System.IO
import System.Exit
import System.Glib.MainLoop as Glib
import System.Glib.Signals as Glib
import System.Glib.Properties as Glib


makeElement:: String → String → IO GS.Element
makeElement elementType elementName = do
element ← GS.elementFactoryMake elementType (Just elementName)
case element of
Just element' → return element'
Nothing → do
hPutStrLn stdout ("Cannot create element!")
hFlush stdout
exitFailure

player = do
GS.init

pipeline ← GS.pipelineNew "video-stream"

source ← makeElement "v4l2src" "video-source"
color ← makeElement "ffmpegcolorspace" "video-color"
tee ← makeElement "tee" "stream-tee"
rQ ← makeElement "queue" "record-queue"
vQ ← makeElement "queue" "video-queue"
encoder ← makeElement "y4menc" "video-encoder"
rSink ← makeElement "filesink" "record-sink"
sink ← makeElement "ximagesink" "video-sink"

let elements = [source,color,encoder,rSink,vQ,rQ,sink,tee]

Glib.objectSetPropertyString "location" rSink "rec"

mapM_ (GS.binAdd (GS.castToBin pipeline)) elements

-- Request Pads from tee
dPad ← GS.elementGetRequestPad tee "src%d"
rPad ← GS.elementGetRequestPad tee "src%d"
-- Request Static Pads from queue
sDPad ← GS.elementGetStaticPad vQ "sink"
sRPad ← GS.elementGetStaticPad rQ "sink"
-- Link tee source to queue sink
GS.padLink (fromJust dPad) (fromJust sDPad)
GS.padLink (fromJust rPad) (fromJust sRPad)

GS.elementReleaseRequestPad tee $ fromJust dPad
GS.elementReleaseRequestPad tee $ fromJust rPad

GS.elementLink source color
GS.elementLink color tee
GS.elementLink vQ sink
GS.elementLink rQ encoder
GS.elementLink encoder rSink


GS.elementSetState pipeline GS.StatePlaying

main = do
loop ← Glib.mainLoopNew Nothing False
player
Glib.mainLoopRun loop

代码编译得很好,相机 LED 亮起,文件被创建,但什么都没有。
如果没有 tee 和 queue 元素,用于录制/显示视频的单独设置就可以正常工作。此外,如果我使用 gst-launch 对其进行测试,相同的管道也可以完美运行。
我在这里遗漏了一些关于 gstreamer 如何工作的内容,但我不知道是什么。

另外,如果有帮助,我正在 ArchLinux 上使用:
- GHC 7.0.3;
- gstreamer 绑定(bind) 0.12.1 ;
- gtk2hs 0.12.2;
- gstreamer 0.10.35-1;
- 油嘴滑舌 1.2.10-9。

最佳答案

已解决

我找到了我的解决方案,接下来是一篇很长的帖子,但请多多包涵。我必须与某人分享我的挫败感。

经过多次错误尝试后,我决定重新使用 gst-launch 测试一些设置。
这帮助我发现,在缓冲进入文件接收器的部分的队列元素之后,我需要另一个 ffmpegcolorspace 元素来设置我认为的正确视频格式。
在这一点上,我不会再用 Haskell 来尝试这个东西了,我认为我需要“更接近”,所以我决定在 C 中尝试它。
作为旁注,我不知道 C ,我可以理解语法,但仅此而已......为了上帝的缘故,我现在正在尝试学习 Haskell。
为了继续,我决定也尝试在 tee 元素上使用“GS.elementGetCompatiblePad”,这样我可以确定垫将与队列链接。

我拼接在一起的 C 代码是这样的:

#include <gst/gst.h>
#include <glib.h>

int
main (int argc,char *argv[])
{

GstElement *pipeline, *source, *color, *color2 , *color3, *tee, *rQ, *vQ, *encoder, *fSink , *sink;
GMainLoop *loop;
loop = g_main_loop_new (NULL,FALSE);
/* initialize gstreamer */
gst_init(&argc,&argv);

/* creating elements */
pipeline = gst_pipeline_new("stream-pipeline");

source = gst_element_factory_make ("v4l2src","stream-source");
color = gst_element_factory_make ("ffmpegcolorspace","video-color");
tee = gst_element_factory_make ("tee","stream-tee");
rQ = gst_element_factory_make ("queue","record-queue");
vQ = gst_element_factory_make ("queue","video-queue");
encoder = gst_element_factory_make ("theoraenc","video-encoder");
fSink = gst_element_factory_make ("filesink","record-sink");
sink = gst_element_factory_make ("ximagesink","video-sink");
color2 = gst_element_factory_make ("ffmpegcolorspace","video-color2");
color3 = gst_element_factory_make ("ffmpegcolorspace","video-color3");
/*check that the elements were created */

if (!source || !color || !tee || !rQ || !vQ || !encoder || !fSink || !sink){
g_printerr("One element could not be created!");
return -1;
}
/*set file output location */
g_object_set(G_OBJECT (fSink),"location","rec",NULL);

gst_bin_add_many (GST_BIN(pipeline),
source,color,color2,color3,tee,rQ,vQ,encoder,fSink,sink,NULL);

/* get request pads */
GstPad *dPad, *rPad, *sDPad, *sRPad;

sDPad = gst_element_get_static_pad(vQ,"sink");
sRPad = gst_element_get_static_pad(rQ,"sink");
dPad = gst_element_get_compatible_pad(tee,sDPad,GST_CAPS_ANY);
rPad = gst_element_get_compatible_pad(tee,sRPad,GST_CAPS_ANY);

/*link pads*/
gst_pad_link(dPad,sDPad);
gst_pad_link(rPad,sRPad);

/*unref pads */
gst_object_unref(GST_OBJECT(dPad));
gst_object_unref(GST_OBJECT(rPad));
gst_object_unref(GST_OBJECT(sDPad));
gst_object_unref(GST_OBJECT(sRPad));

/*link elements */
gst_element_link(source,tee);
gst_element_link_many(rQ,color2,encoder,fSink,NULL);
gst_element_link_many(vQ,color3,sink),NULL;

/*set the pipeline state to playing */
gst_element_set_state(pipeline,GST_STATE_PLAYING);

g_main_loop_run (loop);

gst_element_set_state(pipeline,GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));

return 0;

}

为了使用“gst_element_get_compatible_pad”,我必须首先从队列元素中获取静态填充,所以我手动切换这四个相关行。
我试了一下,Abracadabra ......哦,不,等等......相机启动,文件被创建并弹出一个带有“视频”的窗口,但一个黑色的窗口仍然是黑色的!

我说没问题,用 gst-debug-level=5 (=)) 运行程序)是的,对,尝试阅读整个输出。我暂时放弃了,我想也许它与元素有关我的管道不能正常工作,所以我用 C 编写了另一个管道,但这次更简单的是音频文件。
我得到了相同的结果,所以我决定再次调试,这次使用运行级别 3,我开始逐行阅读整个内容。

在那里的某个地方我发现了这个:


trying to link stream-tee:src0 and record-queue:sink
trying to link stream-tee:src0 and video-queue:sink



这里发生了一些令人讨厌的事情


linked stream-tee:src0 and video-queue:sink,successful
trying to link stream-tee:src0 and record-queue:sink
src stream-tee:src0 was already linked with video-queue:sink



它放弃了!
我想我必须使用 gst_element_get_request_pad 回去,但我还没有尝试过吗?
所以我切换回 vim 并将所有出现的 'gst_element_get_compatible_pad 替换为请求对应项,如下所示:
sDPad = gst_element_get_static_pad(vQ,"sink");
sRPad = gst_element_get_static_pad(rQ,"sink");
dPad = gst_element_get_request_pad(tee,"src%d");
rPad = gst_element_get_request_pad(tee,"src%d");

我凝视着这段代码,我对自己说“你这个笨蛋”,这就是一切的开始;深呼吸;毕竟这是调试器提示的,所以我编译,我运行,瞧。我找到了我的解决方案。

这四行必须颠倒,我必须首先获得对静态垫的引用,然后请求对 tee 元素上的“请求”垫的引用。
我回到haskell一个快乐的人。我实现了我的解决方案,编译,启动,相机启动,文件被创建......就像那样......什么都没有,甚至没有黑屏。
充满愤怒,我只是注释掉我释放请求垫并决定再次编译和运行的行,我的脖子前一阵子开始受伤。
再次,神奇地一切正常,我在屏幕和文件中都有视频。
我猜 Haskell 只是喜欢握得更紧,有时你不得不去做一些没有意义的事情。 gstreamer 文档清楚地说明了发布、发布、发布。

最终的 Haskell 代码:
module Main(main) where

import qualified Media.Streaming.GStreamer as GS
import Data.Maybe
import System.Exit
import System.Glib.MainLoop as Glib
import System.Glib.Signals as Glib
import System.Glib.Properties as Glib

makeElement:: String → String → IO GS.Element
makeElement elementType elementName = do
element ← GS.elementFactoryMake elementType (Just elementName)
case element of
Just element' → return element'
Nothing → do
putStrLn "Cannot create element!"
exitFailure

linkSPadToStaticSink::(GS.ElementClass object, GS.ElementClass elementT) ⇒ object → elementT → IO (Glib.ConnectId object)
linkSPadToStaticSink elSrc elSink = do
Glib.on elSrc GS.elementPadAdded (λpad → do
sinkPad ← GS.elementGetStaticPad elSink "sink"
GS.padLink pad (fromJust sinkPad)
return ∅)

player = do
GS.init
pipeline ← GS.pipelineNew "video-stream"
source ← makeElement "v4l2src" "video-source"
color ← makeElement "ffmpegcolorspace" "video-color"
color2 ← makeElement "ffmpegcolorspace" "video-color2"
tee ← makeElement "tee" "stream-tee"
rQ ← makeElement "queue" "record-queue"
vQ ← makeElement "queue" "video-queue"
encoder ← makeElement "y4menc" "video-encoder"
rSink ← makeElement "filesink" "record-sink"
sink ← makeElement "ximagesink" "video-sink"

let elements = [source,color,color2,encoder,rSink,vQ,rQ,sink,tee]

Glib.objectSetPropertyString "location" rSink "rec"

mapM_ (GS.binAdd (GS.castToBin pipeline)) elements

-- Get static pads from queue elements
sDPad ← GS.elementGetStaticPad vQ "sink"
sRPad ← GS.elementGetStaticPad rQ "sink"
-- Request pads from tee element
dPad ← GS.elementGetRequestPad tee "src%d"
rPad ← GS.elementGetRequestPad tee "src%d"
-- Link tee source to queue sink
GS.padLink (fromJust dPad) (fromJust sDPad)
GS.padLink (fromJust rPad) (fromJust sRPad)

GS.elementLink source color
GS.elementLink color tee
GS.elementLink vQ sink
GS.elementLink rQ color2
GS.elementLink color2 encoder
GS.elementLink encoder rSink

GS.elementSetState pipeline GS.StatePlaying

main = do
loop ← Glib.mainLoopNew Nothing False
player
Glib.mainLoopRun loop

现在我问你,我应该/可以看到这个吗?
有那么明显吗?

我很高兴这会让我更加小心,并在不那么明显的地方看,但是......哇。

总之,我了解了 gstreamer 调试选项,我了解到它对我耳语,我必须听。我了解到 GDB 被迫使用,因为当我开始拼接 C 代码时,我得到的只是一个“段错误”。我学会了喜欢惰性 eval 和纯 Haskell 代码。一点点 Haskell,也许一点点 C 和更多经验。
“迷失”了大约半天,三节课和几个小时的 sleep ,但毕竟... 就这样...

关于Haskell GStreamer tee element(1-N) 麻烦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8555893/

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