2011-12-19 33 views
9

Vấn đề tôi có liên quan đến các đoạn mã sau:Haskell GStreamer tee yếu tố (1-N) rắc rối

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 

mã biên dịch tốt, camera LED chuyển sang ON và các tập tin được tạo ra nhưng sau đó KHÔNG CÓ GÌ. Nếu không có các yếu tố tee và hàng đợi, thiết lập riêng biệt để ghi/hiển thị video hoạt động tốt. Ngoài ra, cùng một đường ống hoạt động hoàn hảo nếu tôi thử nghiệm nó với gst-launch. Tôi đang thiếu một cái gì đó ở đây về cách làm việc gstreamer nhưng tôi không thể tìm ra những gì.

Ngoài ra, nếu có, tôi đang xây dựng trên ArchLinux sử dụng:
- GHC 7.0.3;
- gstreamer-bindings 0.12.1;
- gtk2hs 0,12,2;
- gstreamer 0.10.35-1;
- glib 1.2.10-9.

+0

Bạn nên thêm những khám phá của bạn như là một câu trả lời và chấp nhận câu trả lời đó. Nó không được coi là thô lỗ để trả lời câu hỏi của riêng bạn ở đây - nếu bạn đã xảy ra là người đầu tiên khám phá những gì đã sai, nhiều quyền lực hơn cho bạn! –

Trả lời

10

QUYẾT

tôi tìm thấy giải pháp của tôi, và những gì sau là một bài dài nhưng làm ơn, trần với tôi, tôi phải chia sẻ sự thất vọng của tôi với một ai đó.

Sau nhiều lần thử nhiều lần, tôi quyết định quay trở lại để thử nghiệm một số thiết lập bằng gst-launch. Điều này đã giúp tôi tìm ra rằng sau khi phần tử xếp hàng đệm phần mà đi đến các tập tin tôi cần một yếu tố ffmpegcolorspace để thiết lập các định dạng video chính xác tôi nghĩ. Tại thời điểm này tôi đã không trở lại để cố gắng điều này ra nó Haskell một lần nữa, tôi nghĩ rằng tôi cần thiết để có được 'gần gũi hơn' vì vậy tôi quyết định thử nó trong C. Như một mặt lưu ý, tôi không biết C, tôi có thể hiểu cú pháp nhưng đó là về nó ... và vì sự tốt lành vì tôi chỉ đang cố học Haskell. Để tiếp tục, tôi quyết định thử sử dụng 'GS.elementGetCompatiblePad' trên phần tử tee để tôi có thể chắc chắn rằng các miếng đệm sẽ liên kết với hàng đợi.

Mã C i khâu lại với nhau là thế này:

#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; 

} 


Để sử dụng 'gst_element_get_compatible_pad' tôi đã phải đầu tiên có được miếng đệm tĩnh từ các yếu tố hàng đợi vì vậy tôi tay để chuyển những bốn dây chuyền liên quan. Tôi dùng thử, và Abracadabra ... ồ không, chờ ... camera bắt đầu, tập tin được tạo và một cửa sổ có cửa sổ 'video', nhưng một cửa sổ đen vẫn còn đen!


Không có vấn đề gì tôi nói, hãy chạy chương trình với gst-debug-level = 5 (=))) yea, phải, thử đọc toàn bộ output.I bỏ cuộc và tôi nghĩ có lẽ nó có thứ gì đó làm với các yếu tố trong đường ống của tôi không làm việc ngay với nhau vì vậy tôi mã một đường ống trong C nhưng lần này một cái gì đó đơn giản hơn chỉ với các tập tin âm thanh.
Tôi đã có kết quả tương tự vì vậy tôi quyết định tu gỡ lỗi một lần nữa, lần này với runlevel 3 và tôi bắt đầu đọc toàn bộ điều, từng dòng một.


Một nơi nào đó ở đó tôi thấy điều này:


cố gắng liên kết dòng chữ I: src0 và kỷ lục đợi: chìm
cố gắng liên kết dòng chữ I: src0 và video đợi: chìm


một cái gì đó khó chịu đang xảy ra ở đây


liên kết luồng-tee: src0 và video-queue: sink, thành công
cố gắng liên kết stream-tee: src0 và record-queue: sink
src stream-tee: src0 đã được liên kết với video-queue: sink


Và nó bỏ cuộc!
Tôi đoán tôi phải quay trở lại bằng cách sử dụng gst_element_get_request_pad, nhưng tôi chưa thử điều đó chưa? Vì vậy, tôi chuyển về vim và thay thế tất cả các lần xuất hiện của 'gst_element_get_compatible_pad với các đối tác yêu cầu như vậy:

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"); 


Tôi nhìn vào mã này và tôi nói với bản thân mình 'bạn twit', đây là nơi mà tất cả bắt đầu ; hít một hơi thật sâu; sau khi tất cả điều này là những gì trình gỡ lỗi phàn nàn về vì vậy tôi biên dịch, tôi chạy, và Voila. Tôi tìm thấy giải pháp của tôi.


Bốn dòng này phải được đảo ngược, trước tiên tôi phải có tham chiếu đến các miếng đệm tĩnh và sau đó yêu cầu tham chiếu đến miếng đệm 'yêu cầu' trên phần tử tee.
Tôi quay trở lại haskell một người đàn ông hạnh phúc.Tôi thực hiện giải pháp của tôi, biên dịch, cháy lên, máy ảnh bắt đầu, các tập tin được tạo ra và ... chỉ cần như vậy..nothing, thậm chí không màn hình màu đen.
Đầy giận dữ tôi chỉ bình luận ra những dòng mà tôi phát hành các miếng đệm yêu cầu và quyết định biên dịch và chạy một lần nữa, cổ của tôi bắt đầu bị tổn thương một thời gian trước đây.
Một lần nữa, bằng phép thuật, tất cả đều hoạt động, tôi có video trên màn hình và trong tệp.
Tôi đoán Haskell chỉ thích giữ chặt hơn và đôi khi bạn phải chỉ cần đi với một cái gì đó mà không có ý nghĩa. Các tài liệu gstreamer tuyên bố rõ ràng phát hành, phát hành, phát hành.

Mã Haskell thức:

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 


Bây giờ tôi hỏi bạn, nên/có thể tôi đã thấy điều này?
Điều đó có hiển nhiên không?


Tôi rất vui vì điều này sẽ làm cho tôi cẩn thận hơn và nhìn vào những nơi không rõ ràng nhưng ... eww.

Tóm lại để tất cả điều này, tôi đã học được về các tùy chọn GStreamer gỡ lỗi, tôi đã học được rằng nó thì thầm với tôi và tôi phải lắng nghe. Tôi đã học được về GDB bị buộc phải sử dụng bởi vì khi tôi bắt đầu khâu C mã tất cả tôi đã nhận được là một 'seg lỗi'.
Tôi đã học cách yêu mã lười biếng-eval và Haskell thuần túy.
Một chút Haskell, có thể là một chút xíu của C và nhiều kinh nghiệm hơn. 'Lost' khoảng nửa ngày, ba lớp và một số giờ ngủ nhưng sau khi tất cả ... Vì vậy, nó đi ...

Các vấn đề liên quan