RESUELVE
encontré mi solución, y lo que sigue es un post largo, pero por favor, desnuda conmigo, debo compartir mi frustración con alguien.
Después de muchos más intentos fallidos, decidí volver a probar algunas configuraciones usando gst-launch. Esto me ayudó a descubrir que después del elemento de la cola que almacena en búfer la parte que va al filesink, necesitaba otro elemento ffmpegcolorspace para configurar el formato de video correcto, creo. En este punto no iba a volver a probar Haskell otra vez, pensé que necesitaba acercarme, así que decidí probarlo en C. Como nota al margen, no sé C, yo puede entender la sintaxis, pero eso es todo ... y por Dios, ahora estoy tratando de aprender Haskell. Para continuar, decidí también intentar usar 'GS.elementGetCompatiblePad' en el elemento de salida, así puedo estar seguro de que los pads se vincularán con la cola.
El código C i cosidos entre sí es la siguiente:
#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;
}
Para utilizar 'gst_element_get_compatible_pad' que tenía que conseguir primero almohadillas estáticos a partir de los elementos de la cola de la mano, así que para cambiar esas cuatro líneas relacionadas. Lo pruebo, y Abracadabra ... oh no, espera ... la cámara se inicia, se crea el archivo y aparece una ventana con el 'video', ¡pero una ventana negra que permanece negra!
No hay problema, digo, ejecute el programa con gst-debug-level = 5 (=))) Sí, correcto, intente leer toda la salida. Me rindo por el momento y pensé que tal vez tenía algo que hacer con los elementos en mi tubería que no funcionan bien juntos así que código otra tubería en C, pero esta vez algo más simple solo con archivos de audio.
Tuve el mismo resultado, así que decidí depurar de nuevo, esta vez con el nivel de ejecución 3 y comencé a leer todo, línea por línea.
En alguna parte he encontrado esto:
tratar de vincular corriente-T: src0 y el archivo de cola: se hunden
tratar de vincular corriente-T: src0 y el video-cola: hundirse
algo desagradable que está pasando aquí
ligado corriente-T: src0 y el video-cola: fregadero, éxito
tratar de vincular corriente-T: src0 y el archivo de cola: se hunden
src corriente-T: src0 ya estaba vinculado con el vídeo-cola: fregadero
¡Y se da por vencido!
Supongo que debo volver usando gst_element_get_request_pad, pero ¿no lo he intentado ya? Así Puedo volver a vim y reemplazar todas las ocurrencias de 'gst_element_get_compatible_pad con la solicitud de contraparte de este modo:
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");
contemplo este código y me digo 'que Twit', esto es donde empezó todo ; Tomar una respiración profunda ; después de todo esto es de lo que se queja el depurador así compilo, corro y Voila. Encontré mi solución.
Esas cuatro líneas tuvieron que invertirse, primero tuve que hacer una referencia a las almohadillas estáticas y luego solicitar una referencia a una almohadilla de 'solicitud' en el elemento tee.
Vuelvo a tener a Haskell como un hombre feliz. Implemento mi solución, compilo, enciendo, la cámara se inicia, el archivo se crea y ... así ... nada, ni siquiera la pantalla en negro.
Lleno de enojo, solo comento las líneas en las que lanzo los paneles de solicitud y decido compilar y ejecutar una vez más, mi cuello comenzó a doler hace un tiempo.
Nuevamente, por arte de magia, todo funciona, tengo video en la pantalla y en el archivo.
Supongo que a Haskell le gusta apretarse más y a veces solo tiene que ir con algo que no tiene sentido. El estado de los documentos gstreamer libera, libera y libera claramente.
El código Haskell definitiva:
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
Ahora te pregunto, debería/podría yo haber visto esto?
¿Era tan obvio?
Me alegra que esto me haga ser más cuidadoso y buscar en lugares no tan obvios, pero ... eww.
Como conclusión de todo esto, aprendí sobre las opciones de depuración gstreamer, aprendí que me susurra y DEBO escuchar. Aprendí sobre GDB forzado a usar porque cuando comencé a coser código C, todo lo que obtuve fue un "fallo seg".
Aprendí a amar lazy-eval y el código Haskell puro.
Un poco de Haskell, tal vez un poquito de C y más experiencia. 'perdido' alrededor de la mitad de un día, tres clases y varias horas de sueño, pero después de todo ... por lo que pasa ...
Debe añadir sus descubrimientos como una respuesta y aceptar esa respuesta. No se considera grosero responder a su propia pregunta aquí: si resultó ser el primero en descubrir lo que estaba mal, ¡más poder para usted! –