我遇到的问题与以下代码有关:
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和队列元素,用于录制/显示视频的单独设置工作正常。如果我使用gst-launch测试它,同样的管道也能正常工作。 我在这里遗漏了一些关于gstreamer如何工作但我无法弄清楚是什么的东西。
此外,如果它有帮助,我正在使用ArchLinux构建:
- GHC 7.0.3;
- gstreamer-bindings 0.12.1;
- gtk2hs 0.12.2;
- gstreamer 0.10.35-1;
- glib 1.2.10-9。
答案 0 :(得分:10)
<强>分辨强>
我找到了我的解决方案,接下来是一篇很长的帖子,但是请耐心等待。我必须与某人分享我的挫折感。
经过更多的错误尝试后,我决定回去使用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,我开始逐行阅读整个事情。
在某处我发现了这个:
尝试链接stream-tee:src0和record-queue:sink
试图链接stream-tee:src0和video-queue:sink
这里发生了令人讨厌的事情
链接
链接的stream-tee:src0和video-queue:sink,成功
试图链接stream-tee:src0和record-queue:sink
src stream-tee:src0已与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");
我凝视这段代码,我对自己说'你蠢',这就是一切开始的地方;深呼吸;毕竟这是调试器所抱怨的,所以我编译,我运行,和Voila。我找到了解决方案。
这四条线必须颠倒,我必须首先获得静态垫的参考,然后请求引用T形元件上的“请求”垫。
我回到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和更多的经验。
'迷失'大约半天,三节课和几个小时的睡眠但毕竟...... 所以它会......