iMotion

Cela faisait un moment que je n’avais plus posté sur iMotion, en août dernier apparemment !

J’ai repris le code pour y ajouter le support des fichiers vidéos. Je butais depuis un moment sur un problème de fige de la vidéo lors du changement d’un effet pendant la lecture, problème que je n’ai pas avec la webcam. Cette technique de changement dynamique d’un élément lors de la lecture dans le pipeline est uniquement documenté ici : cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/design/part-block.txt#n112 mais je n’ai pas trouvé de soft qui l’implémente …

Premièrement j’avais oublié l’indication 8 :

8) make sure element4 is in the same state as the rest of the elements. The element should at least be PAUSED.

Mon pipeline est en statut PLAYING donc en passant l’élément effect dans ce statut le problème de fige de la vidéo a été résolu.

Deuxièmement le schéma de la documentation montre un pipeline de 3 éléments (plus un 4 ème qui remplace dynamiquement le 2ème). Or cela m’a induis en erreur car le mien en possède 6 :

  1. filesrc
  2. decodebin2
  3. ffmpegcolorspace
  4. videoscale
  5. effectv
  6. ximagesink

Lorsque la documentation indique de bloquer l’élément 1 il s’agit en fait de l’élément qui précède celui que l’on veut remplacer. Dans iMotion je souhaite changer dynamiquement d’effet donc c’est l’élément 4 qui doit être bloqué.

Pour ceux qui débutent avec GStreamer voici une excellente présentation : blog.nicolargo.com/2009/03/gstreamer-la-theorie.html

Voici une capture d’écran avec l’effet edgetv suivie de l’implémentation correcte du code :

voidVideoManager::switch_effect (Glib::ustring a_name){   m_effect_name = a_name;   bool res = false;   GstEvent *event;

   // replay pipeline if it paused

   gst_element_get_state(m_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);   gst_element_set_state (m_pipeline, GST_STATE_PLAYING);

   // wait until pipeline playing   if (gst_element_get_state (m_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) {std::cout << "Failed to go into PLAYING state" << std::endl;exit(1);}

std::cout << "PLAYING state" << std::endl;

GstPad *videoscale_sink_pad = gst_element_get_static_pad (m_videoscale, "sink");GstPad *videoscale_src_pad = gst_element_get_static_pad (m_videoscale, "src");

if (videoscale_src_pad) {res = gst_pad_set_blocked_async (videoscale_src_pad, TRUE, (GstPadBlockCallback) block_callback, m_pipeline);std::cout << "blocked pad : " << res << std::endl;

if (!res) {std::cout << "can not block source pad : " << res << std::endl;exit (1);} else {std::cout << "blocked source pad : " << res << std::endl;}

}else {std::cout << "can not get source pad : " << res << std::endl;exit (1);}

if (m_effect){GstPad *effect_sink_pad = gst_element_get_static_pad (m_effect, "sink");GstPad *effect_src_pad = gst_element_get_static_pad (m_effect, "src");

// remove effect elementgst_element_get_state(m_effect, NULL, NULL, GST_CLOCK_TIME_NONE);gst_element_set_state (m_effect, GST_STATE_NULL);gst_element_get_state(m_effect, NULL, NULL, GST_CLOCK_TIME_NONE);

if (gst_element_get_state (m_effect, NULL, NULL, GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) {std::cout << "Failed to state null on m_effect" << std::endl;exit(1);}

gst_element_unlink_pads (m_videoscale,"src",m_effect,"sink");

std::cout << "UNLINK PAD" << std::endl;

/************ seems to not be usefull ************/gst_pad_add_event_probe (effect_src_pad, G_CALLBACK (source_pad_event_probe), effect_src_pad);event = gst_event_new_eos ();gst_pad_send_event (effect_sink_pad, event);gst_object_unref (effect_sink_pad);std::cout << "SEND EOS" << std::endl;/**************************************************/

gst_element_unlink_pads (m_effect,"src",m_sink,"sink");

std::cout << "UNLINK PAD 2" << std::endl;gst_element_get_state(m_effect, NULL, NULL, GST_CLOCK_TIME_NONE);

gst_bin_remove (GST_BIN (m_bin), m_effect);

std::cout << "GST BIN REMOVED" << std::endl;

}else{gst_element_unlink_pads (m_videoscale,"src",m_sink,"sink");}

if ( m_effect_name != "none"){m_effect = gst_element_factory_make (m_effect_name.c_str(), "effect");gst_bin_add (GST_BIN (m_bin), m_effect);gst_element_link_pads (m_videoscale,"src",m_effect,"sink");gst_element_link_pads (m_effect,"src",m_sink,"sink");

// Indication 8gst_element_set_state (m_effect, GST_STATE_PLAYING);       std::cout << "new effect and linked in" << std::endl;   }   else   {       gst_element_link_pads (m_videoscale,                              "src",                              m_sink,                              "sink");

       m_effect = 0;       std::cout << "no effect" << std::endl;

   }

   if (videoscale_src_pad) {       res = gst_pad_set_blocked_async (videoscale_src_pad, FALSE,(GstPadBlockCallback) block_callback, m_pipeline);       gst_object_unref (videoscale_src_pad);   }    std::cout << "unblocked source pad : " << res << std::endl;    std::cout << m_effect_name << std::endl;}
  1. #1 par Hamadi MESSOUD le 22 juin 2010 - 11:15

    Bonjour,
    je travaille actuellement sur un projet qui utilise la bibliothèque Gstreamer, donc je suis en train d’ecrire un programme en C qui demultiplixé uf flux mpegts en utilisant gstreamer pour demultiplixer le flux et afficher l’image et le son d’un programme TV qui se trouve dans le flux. J’ai un probleme lorsque je vai augmenter ou deminuer le volume il faut que la partie d’affichage reste en etat Playing alors que je doit modifier uniquement la proprieté volume de l’element VOLUME, j’utilise ta methode pour creé un nouveau element volume avec la nouvelle valeur mais sa ne marche pas:/ est ce que tu peu m’aider. c’est un projet IPTV donc le volume doit etre modifier en utilisant une telécommande qui envoi un signal asynchrone au recepteur et puis mon programme prend cette interruption je pense en charge.

    Merci beacoup :) )

    • #2 par fredix le 22 juin 2010 - 12:06

      Bonjour,
      ca fait un moment que je n’ai plus touché à mon soft donc à chaud je peux pas te répondre. Le mieux est d’aller sur IRC irc.freenode.net #gstreamer

  2. #3 par Hamadi MESSOUD le 22 juin 2010 - 12:16

    Merci beaucoup meme pour ta reponse rapide.

    bonne journé mon ami

Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Gravatar
Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Twitter picture

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Connexion à %s

Suivre

Get every new post delivered to your Inbox.

Joignez-vous à 189 followers