Archive

Archive de la Catégorie ‘gtkmm’

iMotion

1 juin 2009 fredix 3 commentaires

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

Tutoriels C/C++

Il y a bien 12 ans j’étais convaincu qu’un jour je me mettrais vraiment au C++, juste que je n’avais pas prévu mettre autant de temps :) S’il y en a qui ont tendance à procrastiner comme moi, voici de quoi gagner quelques années.

J’ai découvert il y a peu 2 superbes tutoriels qui permettent d’apprendre les langages C et C++ : Apprenez à programmer en C ! , Apprenez à programmer en C++ !. Excellent car l’auteur est très pédagogue et a la capacité de poser les questions que l’on se pose à mesure de la lecture et d’y répondre.

Il n’y a pas photo, le C++ simplifie énormément le C … Par exemple le CIN et COUT qui remplacent aisément le printf, la possibilité d’utiliser des références à la place des pointeurs, le new qui détecte automatiquement la taille à allouer et donc nul besoin d’effectuer un sizeof, le type bool, le possibilité de déclarer une variable n’importe où même dans la déclaration d’une boucle, le typedef automatique, les valeurs par défaut dans les paramètres des fonctions, la surcharge des fonctions, les fonction inline, et bien sûr tout ce qui est spécifique à la POO.

A mon avis il est quand même nécessaire de comprendre un minimum le C même s’il est possible d’apprendre directement le C++ . Cependant je pense que Ruby est à mon avis un meilleur moyen d’apprendre la programmation et la POO avant d’attaquer le C++ . C -> Ruby -> C++ ou Ruby -> C -> C++ est un bon parcours d’apprentissage.

Évidement en C++ pur on ne fait pas grand chose et il est nécessaire d’apprendre l’usage d’une bibliothèque graphique si on souhaite faire des IHM. Mais quoi qu’il en soit ce langage ouvre toutes sortes de perspectives (embarqué, client desktop, serveur, extensions, …) choses difficiles à obtenir avec des langages plus simple de haut niveau.

D’autres tutoriels complémentaires : Cours de C/C++ de Christian Casteyde , Introduction au langage C de Bernard Cassagne

Ah si en 1996 j’avais eu Internet, toutes ces docs, le GNU/Linux actuel et Ruby … Ils sont chanceux les gamins d’aujourd’hui :) .

Catégories:MondeLibre, gtkmm

gtkmm

J’ai enfin décidé de me mettre au C++ et pour débuter faire une IHM à effectv. Je sais qu’il existe Cheese mais effectv est beaucoup plus fourni en effets visuels et mon objectif n’est pas d’en faire un clone.

Pour l’instant rien d’extraordinaire vu que cette application me sert surtout d’apprentissage mais j’arrive néanmoins à afficher ma webcam et à utiliser des filtres d’effets visuels. Il n’y a que 8 effets qui ont été porté d’effectv en plugin GStreamer mais cela sera l’occasion de tenter de porter ceux qui manquent. Pour ceux qui veulent compiler le source voici le dépôt GIT. Attention je ne me suis pas encore mis aux autotools donc il faut lancer le script compile dans le répertoire script en ayant auparavant modifié la constante DATADIR dans imotionapp.h et installé les bibliothèques de développement gtkmm, libglademm et gstreamermm.

Merci au guru master Dodji pour ses tuyaux :)

un screenshot avec l’effet dicetv :

Catégories:MondeLibre, gtkmm, imotion