2013-10-02 4 views
2

J'essaie de superposer une image .png (avec un canal alpha) sur GStreamer-1.0 pour une application que je suis en train d'écrire, mais, après beaucoup de recherche sur le Web et la lecture de la documentation I » Je suis encore un peu confus avec la méthode à utiliser.Changer le format vidéo sur GStreamer

La méthode que je me sers est:

filesrc -> pngdec -> imagefreeze -> videoconvert -> videoscale -> videomixer -> output_of_bin input_of_bin -> videoconvert -> videoscale -> |

Ceci est une petite section d'une application plus large.

Ma question est la définition des propriétés sur les éléments videoscale et videoconvert, je pense que vous êtes censé utiliser GSTCaps, mais cela ne fonctionne pas. J'ai essayé plusieurs façons. C'est une fonction membre dans une classe qui fournit la superposition. Je m'excuse à l'avance pour le désordre du code, mais c'est expérimental.

bool ImageOverlay::CreateElement() 
{ 
    GstPad *source_pad, *sink_pad; 
    GstElement *file_source, *png_decoder, *freeze, *colorspace, 
     *video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2; 

    /* Create gstreamer elements */ 
    _image_overlay_element = gst_bin_new("image-player"); 

    if(!_image_overlay_element) 
    { 
    g_printerr ("Pipeline could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create file source 
    file_source = gst_element_factory_make ("multifilesrc", "file-source"); 
    g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL); 

    if(!file_source) 
    { 
    g_printerr ("File could not be created. Exiting.\n"); 
    return false; 
    } 

    // Decode file 
    png_decoder = gst_element_factory_make ("pngdec", "png-decoder"); 
    if(!png_decoder) 
    { 
    g_printerr ("png-decoder could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create colour space convertor 
    colorspace = gst_element_factory_make("videoconvert", "colorspace"); 
    if(!colorspace) 
    { 
    g_printerr ("Colorspace could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create colour space convertor 
    colorspace2 = gst_element_factory_make("videoconvert", "colorspace2"); 
    if(!colorspace) 
    { 
    g_printerr ("Colorspace could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create idenentiy component, does nothing but is useful for debug 
    identity = gst_element_factory_make("identity", "identity"); 
    if(!identity) 
    { 
    g_printerr ("Colorspace could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create a video mixer 
    video_mixer = gst_element_factory_make("videomixer", "mixer"); 
    if(!video_mixer) 
    { 
    g_printerr ("videomixer could not be created. Exiting.\n"); 
    return false; 
    } 

    // Create a freeze element 
    freeze = gst_element_factory_make("imagefreeze", "freeze"); 
    if(!freeze) 
    { 
    g_printerr ("ImageFreeze could not be created. Exiting.\n"); 
    return false; 
    } 

    video_scale_1 = gst_element_factory_make("videoscale", NULL); 
    if(!video_scale_1) 
    { 
    g_printerr ("video_scale_1 could not be created. Exiting.\n"); 
    return false; 
    } 

    video_scale_2 = gst_element_factory_make("videoscale", NULL); 
    if(!video_scale_2) 
    { 
    g_printerr ("video_scale_2 could not be created. Exiting.\n"); 
    return false; 
    } 

    // Add to the bin 
    gst_bin_add_many (GST_BIN (_image_overlay_element), 
        file_source, 
        png_decoder, 
        colorspace, 
        colorspace2, 
        freeze, 
        video_mixer, 
        identity, 
        video_scale_1, 
        video_scale_2, 
        NULL); 


    if (!gst_element_link_many (file_source, png_decoder, video_scale_1, freeze, NULL)) 
    { 
    std::cout << "Could not link" << std::endl; 
    } 

    GstCaps * caps = gst_caps_new_simple ("video/x-raw", 
             "format", G_TYPE_STRING, "ARGB", 
             NULL); 


    GstCaps * caps2 = gst_caps_new_simple("width", G_TYPE_INT, 640, 
             "height", G_TYPE_INT, 480, 
             NULL); 

    gst_element_link_filtered(video_scale_1, freeze, caps2); 
    gst_element_link_filtered(video_scale_2, freeze, caps2); 

    if (!gst_element_link_many(freeze, video_scale_2, colorspace, NULL)) 
    { 
    std::cout << "Could not link" << std::endl; 
    } 

    // Link pads to video mixer 
    GstPad * sink_pad_1 = gst_element_get_request_pad (video_mixer, "sink_%u"); 
    GstPad * sink_pad_2 = gst_element_get_request_pad (video_mixer, "sink_%u"); 
    GstPad * source_2 = gst_element_get_static_pad (identity, "src"); 
    GstPad * source_1 = gst_element_get_static_pad (colorspace, "src"); 

    gst_pad_set_caps(source_2, caps); 
    gst_pad_set_caps(source_1, caps); 
    gst_caps_unref(caps); 

    if (!gst_pad_link (source_1, sink_pad_1) == GST_PAD_LINK_OK) 
    { 
    std::cout << "Could not link pads" << std::endl; 
    return false; 
    } 

    if (!gst_pad_link (source_2, sink_pad_2) == GST_PAD_LINK_OK) 
    { 
    std::cout << "Could not link pads" << std::endl; 
    return false; 
    } 

    gst_pad_set_active(source_1, true); 
    gst_pad_set_active(sink_pad_1, true); 
    gst_pad_set_active(source_2, true); 
    gst_pad_set_active(sink_pad_2, true); 

    // Add pad to this element 
    source_pad = gst_element_get_static_pad (video_mixer, "src"); 
    sink_pad = gst_element_get_static_pad(identity, "sink"); 
    gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("src", source_pad)); 
    gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("sink", sink_pad)); 

    return true; 
} 

Je voudrais prendre les deux sources les redimensionner à la même taille et la superposition de l'image png sur la vidéo. Le bloc fonctionne principalement, mais je ne peux pas faire fonctionner le redimensionnement ou le canal alpha.

Merci,

Edit:

J'ai maintenant modifié mon code et avoir une compréhension un peu mieux, il semble toutefois que le problème est que le capfilter ne sera pas un lien si elle utilise RGBA certains d'autres formats fonctionnent mais ne servent à rien. Je ne sais pas pourquoi.

bool ImageOverlay::MakeElements() 
{ 
    try 
    { 
    // Creates the bin at this level 
    CreatePipeline(); 
    GstElement *file_source, *png_decoder, *freeze, *colorspace, 
     *video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2, *caps_filter1, *caps_filter2; 

    // Create elements 
    file_source = CreateElementAndAddToBin("multifilesrc", "file-source"); 
    png_decoder = CreateElementAndAddToBin("pngdec", "png-decoder"); 
    colorspace = CreateElementAndAddToBin("videoconvert", "colorspace"); 
    colorspace2 = CreateElementAndAddToBin("videoconvert", "colorspace2"); 
    identity  = CreateElementAndAddToBin("identity", "identity"); 
    video_mixer = CreateElementAndAddToBin("videomixer", "mixer"); 
    freeze  = CreateElementAndAddToBin("imagefreeze", "freeze"); 
    video_scale_1 = CreateElementAndAddToBin("videoscale", "scale1"); 
    video_scale_2 = CreateElementAndAddToBin("videoscale", "scale2"); 
    caps_filter1 = CreateElementAndAddToBin("capsfilter", "caps_filter1"); 
    caps_filter2 = CreateElementAndAddToBin("capsfilter", "caps_filter2"); 

    // Set input file 
    g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL); 

    // Create caps 
    GstCaps *caps = gst_caps_new_simple ("video/x-raw", 
             "format", G_TYPE_STRING, "YV12", //<<< IF THIS IS SET TO ARGB (THE FORMAT I WANT IT FAILS ON LINKING) 
             "framerate", GST_TYPE_FRACTION, 25, 1, 
             "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, 
             "width", G_TYPE_INT, 640, 
             "height", G_TYPE_INT, 480, 
             NULL); 


    // Set caps on cap filter 
    g_object_set(G_OBJECT(caps_filter2), "caps", caps, NULL); 
    g_object_set(G_OBJECT(caps_filter1), "caps", caps, NULL); 


    // Link up elements 
    if (!gst_element_link_many (identity, video_scale_2, colorspace2, caps_filter2, video_mixer, NULL)) 
    { 
     std::cout << "Could not link input branch" << std::endl; //<<<< IF ARGB OR OTHER FORMATS SUCH AS RGBA ARE USED 
    }               // IN CAP FILTER, THIS FAILS, SAME WITH BELOW. IT WORKS WITH YV12! 

    if (!gst_element_link_many (file_source, png_decoder, freeze, video_scale_1, colorspace, caps_filter1, video_mixer, NULL)) 
    { 
     std::cout << "Could not link image source branch" << std::endl; 
    } 

    // Add ghost pads to this bin, allowing it to be used as an element 
    SetInputElement(identity); 
    SetOutputElement(video_mixer); 
    } 
    catch(...) 
    { 
    std::cout << "Overlay generator failed to build, exception thrown" << std::endl; 

    // TODO - Clear up in here 
    return false; 
    } 

    return true; 
} 

Répondre

2

Au GStreamer 1.2, videoconversion est assumée par le mélangeur, il sélectionne automatiquement un format alpha si l'un des plaquettes de puits a une valeur alpha.

Si vous pouvez mettre à jour 1.2, le pipeline, vous devez utiliser aura cette forme:

gst-launch-1.0 uridecodebin uri=file:///home/meh/Pictures/pitivi/nicetext.png ! imagefreeze ! videomixer name=m sink_0::zorder=0 ! videoconvert ! autovideosink videotestsrc ! videoscale ! video/x-raw, width=640, height=400 ! m. 

où nicetext.png est un (.png) 640 x 400 fichier image, avec un fond transparent et certains texte aléatoire.

La partie après la videoscale est un capsfilter, vous pouvez créer avec:

gst_element_factory_make("capsfilter", "random_name")

puis définissez ses plafonds propriété avec la largeur et la hauteur dont vous avez besoin. Si cela n'est pas connu à l'avance, vous devrez installer une sonde sur le pad à partir de laquelle vous devez copier la largeur et la hauteur, intercepter l'événement caps et régler les caps sur le capsfilter à ce moment-là.

Si pour une raison quelconque, vous ne pouvez pas utiliser 1.2, alors vous aurez besoin d'un videoconvert et un capsfilter sur les deux branches, et spécifier le format dont vous avez besoin.

+0

Merci s'il vous plaît pouvez-vous voir le modifier à ma question – robby987

+0

Je ne sais pas pourquoi votre code ne fonctionne pas, faisant partie d'une structure plus grande, je crains que je ne peux pas répondre. Si vous parvenez à me fournir un code C autonome qui présente la question que je peux jeter un oeil :) –

+0

je suis passé à GStreamer-1.2 au détriment de certaines autres questions (ubuntu 13.10 a quelques bugs dans), il a ensuite travaillé. Merci de votre aide. – robby987