Tag d'archives : Gstreamer

Ma tentative de faire fonctionner la pipeline avec Java n’a pas été fructueuse. Nicolas R. m’a donc aidée afin de trouver, dans un premier temps, une pipeline qui fonctionnerait en ligne de commande. Mais étant donné que l’on rencontrait toujours la même erreur, Nicolas R.  a pensé qu’il pouvait s’agir d’un problème dû au fait que j’étais sous Debian. J’ai donc réinstallé Ubuntu sur mon ordinateur, mais l’erreur persistait. Etant donné qu’elle était peut-être due à l’utilisation de gstrtpsession, j’ai réecrit mes commandes d’émetteur et de récepteur. Les voici :

Emetteur :

gstrtpbin name=rtpbin rtspsrc location=rtsp://(adresse IP de la camera):554/mpeg4/media.amp ! queue ! decodebin ! x264enc ! rtph264pay ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=5000 host=(adresse IP du récepteur) rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=(adresse IP du client) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0

Récepteur :

gstrtpbin name=rtpbin latency=200 udpsrc caps=\”application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264\” port=5000 ! rtpbin.recv_rtp_sink_0 rtpbin. ! rtph264depay ! ffdec_h264 ! tee ! queue ! ffmpegcolorspace name=vs udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0 rtpbin.send_rtcp_src_0 ! udpsink port=5005 host=127.0.0.1 sync=false async=false

Malheureusement, je n’arriavait toujours pas à trouver de pipeline pour le serveur. J’ai également tenté d’en écrire une comportant deux gstrtpbin, sur les conseils de Nicolas R., mais cela n’a pas été plus fructueux. C’est pourquoi je suis passée à la suite, et j’essaie maintenant de réaliser des classes de tests utilisant celles qu’il a implémentées.

J’ai fini de recoder la partie de mon application qui gère les informations des différents clients, afin de pouvoir aisément envoyer le flux à plusieurs récepteurs. J’ai crée une classe RtpRtcpClientInfos, qui contient uniquement une adresse IP, et trois ports un pour le RTP et deux pour le RTCP, afin de pouvoir récupérer les données des différents clients plus facilement.

J’ai ensuite commencé à recoder la construction de la pipeline du serveur, en me servant de getRequestPad() et prenant exemple de la classe GStreamerRTPBin. Malheureusement, j’ai perdu du temps car cette classe n’était pas à jour, et l’exemple n’était donc pas bon. Il faut, en réalité, utiliser en parallèle le listener padAdded. Celui-ci vérifie ensuite quel est le pad ajouté, avant de le connecter à la bonne source ou au bon sinkpad.

Le problème que j’avais sur ma seconde machine est résolu, il était apparemment dû à une mauvaise résolution de l’écran.

Cependant, mon problème de second client persiste, je n’arrive toujours pas à afficher le flux dessus, qu’il s’agisse d’un client local ou d’un autre ordinateur. En lançant l’utilitaire iftop sur le second ordinateur, il apparaît pourtant clairement qu’il reçoit un flux de l’ordinateur sur lequel est lancé le serveur.

J’ai donc demandé de l’aide à Nicolas R., qui a corrigé ma pipeline. Voici la pipeline qu’il m’a conseillé d’utiliser :

gst-launch gstrtpbin name=rtpbin udpsrc port=5000 caps=”application/x-rtp, media=(string)video” ! rtpbin.recv_rtp_sink_0 udpsrc port=5001 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_0 rtpbin.send_rtcp_src_0 ! udpsink port=5005 host=127.0.0.1 rtpbin.send_rtp_src_0 ! udpsink port=6000 host=127.0.0.1 sync=false async=false rtpbin.send_rtcp_src_0 ! udpsink port=6001 host=127.0.0.1 sync=false async=false udpsrc port=6005 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_0 rtpbin.send_rtp_src_1 ! udpsink port=7000 host=127.0.0.1 sync=false async=false rtpbin.send_rtcp_src_1 ! udpsink port=7001 host=127.0.0.1 sync=false async=false udpsrc port=7005 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_1

Malheureusement, elle ne marche pas en ligne de commande, car les pads sont dynamiques, mais il est probable qu’elle fonctionne avec Java, puisqu’il est possible de spécifier qu’un pad n’est pas statique.

Je suis donc en train de recoder la partie de mon application qui lance le serveur afin qu’elle prenne en compte ces changements. Parallèlement, Nicolas R. m’a conseillé d’étudier un peu la classe GStreamerRTPBin qui se trouve dans JavaMultimedia.

Petite avancée aujourd’hui : j’arrive à afficher le premier client de la pipeline. Voici les commandes que j’utilise :

Émetteur :

./gst-launch -v gstrtpbin name=rtpbin rtspsrc location=rtsp://(adresse de la caméra):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=5000 sync=false async=false host=(adresse du récepteur) rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=(adresse du récepteur) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0 udpsrc port=5006 ! rtpbin.recv_rtcp_sink_1

Serveur :

./gst-launch gstrtpbin name=rtpbin udpsrc port=5000 caps=”application/x-rtp, media=(string)video” ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=6000 sync=false async=false host=(adresse du récepteur 1) udpsrc port=5001 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_0 rtpbin.recv_rtcp_src_0 ! rtpbin.send_rtcp_sink_0 rtpbin.send_rtcp_src_0 ! udpsink port=6001 host=(adresse du récepteur 1) sync=false async=false udpsrc port=6005 ! rtpbin.recv_rtcp_sink_1 rtpbin.recv_rtcp_src_1 ! rtpbin.send_rtcp_sink_1 rtpbin.send_rtcp_src_1 ! udpsink port=5005 host=(adresse du récepteur 2) sync=false async=false rtpbin.send_rtp_src_1 ! udpsink port=7000 host=(adresse du récepteur 2) sync=false async=false rtpbin.recv_rtcp_src_1 ! rtpbin.send_rtcp_sink_1 rtpbin.send_rtcp_src_1 ! udpsink port=7001 host=127.0.0.1 sync=false async=false udpsrc port=7005 ! rtpbin.recv_rtcp_sink_3 rtpbin.recv_rtcp_src_3 ! rtpbin.send_rtcp_sink_3 rtpbin.send_rtcp_src_3 ! udpsink port=5006 host=127.0.0.1 sync=false async=false

Récepteur 1 :

./gst-launch udpsrc port=6000 caps=”application/x-rtp, media=(string)video” ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay ! ffdec_h263 ! xvimagesink udpsrc port=6001 caps=”application/x-rtcp” ! session.recv_rtcp_sink session.send_rtcp_src ! udpsink port=6005 sync=false async=false

Récepteur 2:

./gst-launch udpsrc port=7000 caps=”application/x-rtp, media=(string)video” ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay ! ffdec_h263 ! xvimagesink udpsrc port=7001 caps=”application/x-rtcp” ! session.recv_rtcp_sink session.send_rtcp_src ! udpsink port=7005 sync=false async=false

Cependant, même s’il se lance, le second client n’affiche rien. Sur les conseils de Nicolas H., j’ai effectué ces mêmes tests mais en envoyant le flux du second client sur un autre ordinateur. Pour l’instant, je rencontre quelques problèmes car la seconde machine me renvoie l’erreur suivante :

xvimagesink.c(1639): gst_xvimagesink_xcontext_get (): /autovideosink0-actual-sink-xvimage:

Could not open display

Cependant, mon problème persiste. En effet, si je définis le second client comme étant en local, et le premier client comme étant celui de la seconde machine, si je lance uniquement l’émetteur, le serveur et le second client, rien ne s’affiche. Le problème vient donc sans doute de la pipeline.

Qui-plus-est, au lancement de mon serveur, je reçois l’erreur suivante :

AVERTISSEMENT : de l’élément /GstPipeline:pipeline0 : Internal GStreamer error: clock problem.  Please file a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer.
Information de débogage supplémentaire :
gstbin.c(2213): gst_bin_do_latency_func (): /GstPipeline:pipeline0:
Failed to configure latency of 0:00:00.000000000

J’effectue donc actuellement quelques recherches afin d’en savoir plus sur cette erreur, et je vais continuer d’effectuer quelques tests.

Une partie de ma journée a été occupée en “pichaillonnages” et déménagements.

Sinon, je suis toujours en quête d’un serveur qui renverrai le flux vidéo à plusieurs clients. Néanmoins, je pense ne plus être très loin de la solution. Il doit y avoir une erreur au moment de la connexion du second client, car tant qu’on ne connecte pas le second sourcepad du serveur à un port, le premier client affiche bien le flux vidéo. Voici les commandes sur lesquelles j’ai effectué ces tests :

Émetteur :

./gst-launch -v gstrtpbin name=rtpbin rtspsrc location=rtsp://(adresse de la caméra IP):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=5000 host=(adresse du récepteur) rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=(adresse du récepteur) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0

Serveur :

./gst-launch gstrtpbin name=rtpbin udpsrc port=5000 caps=”application/x-rtp, media=(string)video” ! queue ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=6000 host=(adresse du récepteur 1) udpsrc port=5001 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_0 rtpbin.recv_rtcp_src_0 ! rtpbin.send_rtcp_sink_0 rtpbin.send_rtcp_src_0 ! udpsink port=6001 host=(adresse du récepteur 1) sync=false async=false udpsrc port=6005 ! rtpbin.recv_rtcp_sink_2 rtpbin.recv_rtcp_src_2 ! rtpbin.send_rtcp_sink_2 rtpbin.send_rtcp_src_2 ! udpsink port=5005 host=(adresse du récepteur 2) sync=false async=false rtpbin. ! queue ! rtpbin.recv_rtp_sink_1 rtpbin.recv_rtp_src_1 ! rtpbin.send_rtp_sink_1 rtpbin.send_rtp_src_1 ! udpsink port=7000 host=127.0.0.1 rtpbin.recv_rtcp_src_1 ! rtpbin.send_rtcp_sink_1 rtpbin.send_rtcp_src_1 ! udpsink port=6001 host=(adresse du récepteur 2) sync=false async=false udpsrc port=7005 ! rtpbin.recv_rtcp_sink_3 rtpbin.recv_rtcp_src_3 ! rtpbin.send_rtcp_sink_3 rtpbin.send_rtcp_src_3 ! udpsink port=5006 host=127.0.0.1 sync=false async=false

Récepteur 1 :

./gst-launch udpsrc port=6000 caps=”application/x-rtp, media=(string)video, seqnum-base=(guint)35089″ ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay ! ffdec_h263 ! xvimagesink udpsrc port=6001 caps=”application/x-rtcp” ! session.recv_rtcp_sink session.send_rtcp_src ! udpsink port=6005

Récepteur 2 :

./gst-launch udpsrc port=7000 caps=”application/x-rtp, media=(string)video, seqnum-base=(guint)35089″ ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay ! ffdec_h263 ! xvimagesink udpsrc port=5006 caps=”application/x-rtcp” ! session.recv_rtcp_sink session.send_rtcp_src ! udpsink port=7005

J’ai terminé la classe qui permet d’ajouter plusieurs clients à un récepteur. Cela m’a posé quelques problèmes, car je pensais pouvoir parcourir les enfants de ma liste déroulante et les caster afin de récupérer le contenu de leurs champs. Malheureusement, le cast n’est pas autorisé dans ce cas, et j’ai dû créer une liste à part.

Avant de corriger mes classes de pipeline ainsi que ma classe principale pour qu’elles prennent en compte ces nouveaux paramètres, j’ai voulu trouver les lignes de commandes qui permettent de lancer un serveur communiquant le flux vidéo à plusieurs clients. Mais cela s’avère plus délicat que je ne l’aurais pensé. Il ne suffit apparemment pas de simplement combiner entre elles les dernières lignes de commande que j’ai trouvées. J’ai passé l’essentiel de la journée à chercher comment écrire la pipeline permettant de lancer le serveur, mais je n’ai pour l’instant rien trouvé. J’effectue actuellement quelques essais avec l’élément “queue”, mais sans succès.

Après d’intenses phases de réflexions, de longues batailles avec les paramètres de Gstreamer, et à grand renforts de schémas, j’ai finalement réussi à trouver les lignes de commandes utilisant gstrtpbin permettant de lancer un émetteur de flux vidéo, un serveur, ainsi qu’un récepteur :

Ligne de commande lançant l’émetteur :

./gst-launch -v gstrtpbin name=rtpbin rtspsrc location=rtsp://(adresse de la caméra IP):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=5000 host=(adresse du client) rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=(adresse du client) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0

Ligne de commande lançant le serveur :

./gst-launch gstrtpbin name=rtpbin udpsrc port=5000 caps=”application/x-rtp, media=(string)video” ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! udpsink port=5002 host=(adresse du client) udpsrc port=5001 caps=”application/x-rtcp” ! rtpbin.recv_rtcp_sink_0 rtpbin.recv_rtcp_src_0 ! rtpbin.send_rtcp_sink_0 rtpbin.send_rtcp_src_0 ! udpsink port=5003 host=(adresse du client) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_1 rtpbin.recv_rtcp_src_1 ! rtpbin.send_rtcp_sink_1 rtpbin.send_rtcp_src_1 ! udpsink port=5006 host=(adresse du client) sync=false async=false

Ligne de commande lançant le récepteur :

./gst-launch udpsrc port=5002 caps=”application/x-rtp, media=(string)video, seqnum-base=(guint)35089″ ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay ! ffdec_h263 ! xvimagesink udpsrc port=5003 caps=”application/x-rtcp” ! session.recv_rtcp_sink session.send_rtcp_src ! udpsink port=5005

J’ai donc corrigé mon application afin qu’elle utilise maintenant ces lignes de commande.

Qui-plus-est, j’ai commencé à implémenter une nouvelle classe héritant d’un ScrolledComposite et contentant la liste des clients. J’essaie maintenant de récupérer les enfants de ce composite afin de pouvoir en récupérer les informations, qui me permettront de lancer mon serveur dans le cas où il enverrait le flux vidéo à plusieurs clients.

Je trépigne d’impatience à l’idée de réécrire la ligne de commande du serveur gstrtpbin dans le cas où il y a plusieurs clients!…

J’ai finalement réussi à afficher le flux vidéo de la caméra dans mon application. J’ai effectué quelques tests et tout à l’air de bien fonctionner.

J’ai également trouvé comment me servir de gstrtpbin avec une caméra IP. Il faut en réalité toujours se servir de rtspsrc, comme le montre la ligne de commande suivante, qui permet de streamer le flux vidéo de la caméra vers deux clients différents :

./gst-launch -v gstrtpbin name=rtpbin rtspsrc location=rtsp://(adresse IP de la caméra):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! rtpbin.send_rtp_sink_0 gstrtpsession name=session rtpbin.send_rtp_src_0 ! udpsink port=5000 host=(adresse IP su premier client) rtpbin.send_rtcp_src_0 ! udpsink port=5001 host=(adresse IP su premier client) sync=false async=false udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0 rtspsrc location=rtsp://(adresse IP de la caméra):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! rtpbin.send_rtp_sink_1 gstrtpsession name=sessiontwo rtpbin.send_rtp_src_1 ! udpsink port=5002 host=(adresse IP du second client) sessiontwo.send_rtcp_src_1 ! udpsink port=5003 host=(adresse IP du second client) sync=false async=false udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1

Toutefois, je me pose encore quelques questions car il est probable que cette ligne de commande ne soit pas la plus simple pour streamer un même flux vers deux clients différents.

J’ai également implémenté la partie de l’interface graphique permettant de rentrer les informations des différents clients dans le cas où l’on veut streamer le flux vidéo vers plusieurs clients. Pour cela, j’ai utilisé un ScrolledComposite, c’est-à-dire un composite possédant une liste déroulante contenant tous les contrôles que l’on insère dedans.

J’ai terminé aujourd’hui l’interface graphique de mon application, mais celle-ci ne prend pour le moment qu’un seul client en compte. En effet, en dépit de mes recherches, je ne sais toujours pas comment utiliser gstrtpbin avec une caméra IP. Les quelques exemples de streaming vidéo utilisant Gstreamer et une caméra IP que j’ai pu trouver utilisent tous soit rtspsrc, soit gnomevfssrc.

J’ai également codé la partie Gstreamer de mon application, c’est-à-dire celle qui s’occupe du streaming vidéo. Malheureusement, celle-ci ne fonctionne pas, et je n’arrive pas à cerner pourquoi? Il semblerait pourtant que les pipelines soient bien lancés. Qui-plus-est, hors de l’application (c’est-à-dire si on les lance à partir d’une console), ils fonctionnent très bien. Ce n’est pas non plus l’application qui les bloque, car lorsque l’on lance un pipeline qui se contente d’afficher le flux vidéo de la caméra depuis l’application, cela fonctionne également bien et une fenêtre s’ouvre pour afficher le flux. Je ne vois donc vraiment pas d’où peut provenir le problème.

Maintenant que j’ai un environnement de travail stable, j’ai pu réaliser trois petites applications : la première envoie un flux vidéo à la seconde, qui transmet ce flux à la troisième dont le rôle est de l’afficher. Voici les lignes de commande Gstreamer permettant de réaliser ce travail :

Commande pour lancer la source :

./gst-launch -v rtspsrc location=rtsp://(adresse IP de la webcam):554/mpeg4/media.amp ! queue ! decodebin ! ffenc_h263 ! rtph263pay ! .send_rtp_sink gstrtpsession name=session .send_rtp_src ! udpsink port=5000 host=(adresse IP du relais) session.send_rtcp_src ! udpsink port=5001 host=(adresse IP du relais)

Commande pour lancer le relais

./gst-launch udpsrc port=5000 caps=”application/x-rtp, media=(string)video, seqnum-base=(guint)35089″ ! .recv_rtp_sink gstrtpsession name=sessionrecv .recv_rtp_src ! .send_rtp_sink gstrtpsession name=sessionsend .send_rtp_src ! udpsink port=5002 host=(adresse IP du récepteur) udpsrc port=5001 caps=”application/x-rtcp” ! sessionrecv.recv_rtcp_sink sessionsend.send_rtcp_src ! udpsink port=5003 host=(adresse IP du récepteur)

Commande pour lancer le récepteur/afficheur :

./gst-launch udpsrc port=5002 caps=”application/x-rtp, media=(string)video, seqnum-base=(guint)35089″ ! .recv_rtp_sink gstrtpsession name=session .recv_rtp_src ! rtph263depay !  ffdec_h263 ! xvimagesink udpsrc port=5003 caps=”application/x-rtcp” ! session.recv_rtcp_sink

J’ai ensuite commencé à coder une partie de l’interface graphique de l’application de test qui me servira au final, et j’ai également effectué quelques recherches afin de trouver comment diffuser un flux vidéo à plusieurs clients.