2011-12-19 2 views
9

У меня есть проблема относится к следующей части кода:Haskell GStreamer тройник элемент (1-N) Проблема

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 

Код компилируется нормально, камера светодиод включается и файл создается, но затем НИЧЕГО. Без элементов тройника и очереди отдельная установка для записи/отображения видео работает просто отлично. Также, тот же самый трубопровод работает отлично, если я тестирую его с помощью 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. Это помогло мне узнать, что после элемента queue, который буферизует часть, которая идет в fileink, мне нужен еще один элемент ffmpegcolorspace для настройки правильного формата видео, которое я думаю. В этот момент я не возвращался к этой штуке и не возвращал ее снова, я думал, что мне нужно «подойти», поэтому я решил попробовать его в C. В качестве примечания стороны, я не знаю, C, i может понять синтаксис, но это о нем ... и ради добра я сейчас пытаюсь научиться Haskell. Чтобы продолжить, я решил также попробовать использовать «GS.elementGetCompatiblePad» на элементе tee, поэтому я могу быть уверен, что пэды будут связаны с очередью.

: 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» я должен был сначала получить статические подушечки из элементов очереди, так что я рука, чтобы переключить эти четыре связанные линии. Я пробовал, и Абракадабра ... о нет, подождите ... начинается камера, создается файл и появляется окно с «видео», но черное окно остается черным!


Нет проблем, я говорю, запустите программу с помощью gst-debug-level = 5 (=))) да, попробуйте прочитать весь вывод. Я сдаюсь на данный момент, и я подумал, может быть, у него что-то есть сделайте так, чтобы элементы моего конвейера не работали вместе, поэтому я кодирую другой конвейер в C, но на этот раз что-то более простое с аудиофайлами.
У меня был тот же результат, поэтому я решил снова отладить tu, на этот раз с уровнем запуска 3, и я начал читать все это, строчно.


Где-то там я нашел это:


пытается связать поток двутавровые: src0 и запись-очереди: раковина
пытается связать поток двутавровые: src0 и видео-очереди: раковина


что-то противное, что здесь происходит


связанный поток двутавровые: src0 и видео-очереди: раковина, успешный
пытается связать поток двутавровые: src0 и запись очереди: тонуть
Src поток-тройник: src0 был уже связан с видео-очереди: раковина


И это сдаётся!
Думаю, я должен вернуться с помощью 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. Я нашел решение.


Эти четыре строки должны быть отменены, я должен был сначала получить ссылку на статические прокладки, а затем запросить ссылку на «запрос» на элементе тройника.
Я возвращаюсь к haskell счастливого человека. Я реализую свое решение, компилирую, запускаю, запускает камеру, файл создается и ... так же, как это .. ничего, даже черный экран.
Заполненный гневом, я просто прокомментирую строки, в которых я выпускаю прокладки для запроса, и решают скомпилировать и запустить еще раз, моя шея начала болеть некоторое время назад.
Снова по волшебству все работает, у меня есть видео на экране и в файле.
Я думаю, что Haskell просто любит держаться крепче, и иногда вам нужно просто пойти с чем-то, что не имеет смысла. Gstreamer docs четко заявляет о выпуске, выпуске, выпуске.

Конечный код 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 


Теперь я прошу вас, если/может я видел это?
Было ли это очевидно?


Я рад, что это заставит меня быть более осторожным и смотреть в не столь очевидные места, но ... eww.

В заключение ко всему этому я узнал о вариантах отладки gstreamer, я узнал, что он шепчет мне, и я ДОЛЖЕН слушать. Я узнал о том, что GDB вынужден использовать, потому что, когда я начал сшивать C-код, все, что я получил, было «seg fault».
Я научился любить ленивый и чистый код Хаскелла.
Немного Haskell, может быть, немного C и больше опыта. «Lost» полдня, три класса и несколько часов сна, но все-таки ... Так идет ...

Смежные вопросы