Apresentando o GStreamer

Enviado por setanta em Qua, 07/05/2006 - 07:02. :: Artigos

Versão mais nova: Apresentando o GStreamer

Um dos assuntos onde as pessoas mais discutem (e que começou uma das mais longos debates da lista do CInLUG[1]) é "qual o melhor media player": Xine, VLC, MPlayer, Totem ou {insira o seu prefedido}? Na referida discussão, Jesus (o Sanchez) me pediu pra explicar porque eu acho o GStreamer tão legal, culminando neste artigo.

GStreamer[2] é um framework (acho que se traduz como "arcabouço") para criação de aplicações de fluxo (streaming) de mídia. Fluxo de mídia? Não ficou muito claro, mas framework? O artigo começou como um assunto sobre media players, não está havendo alguma confusão? Sim, está, e um dos motivos deste artigo é definir bem estas diferenças. Por exemplo, muita gente criticava o Totem porque não fazia uma boa sincronia voz-imagem nos vídeos, ou que o dito cujo não tocava vídeos WMV, mas o problema estava no GStreamer, não no Totem. Ele poderia ser criticado pelas funcionalidades não estarem ao gosto do usuário X ou Y, mas não pela sincronia ou ausência de codecs.

Na Terra dos Media Players Monolíticos

Vamos então ver os media players. A figura abaixo mostra um diagrama de três players de vídeo bem conhecidos: Xine, MPlayer e VLC.

O que vemos aqui é bem claro e nada promissor para multimídia no Linux, cada um implementa as mesmas funcionalidades do sua própria maneira, esforços são duplicados, não há cooperação, e as "funcionalidades legais para o usuário" só podem ser implementadas quando toda infra estrutura abaixo estiver funcionando. E piora ainda mais, com cada um usando sua própria estrutura de plug-ins, codecs portados para um não funcionarão no outro. Pelo menos não sem gemidos e ranger de dentes. E estes exemplos tratam apenas de tocadores de vídeo, se incluirmos os tocadores e editores de áudio e os editores de vídeo, vai por água abaixo a esperança do Linux como uma plataforma atraente para desde usuários domésticos até profissionais de multimídia, passando ainda pela arena dos aparelhos portáteis - onde a competição com a M$ e outras empresas de software proprietário é mais acirrada. Não que as aplicações citadas não sejam boas, pelo contrário, são excelentes, algumas inclusive disponibilizam bibliotecas para criação de outras aplicações. Contudo, estas bibliotecas são específicas para decodificar mídia, e se eu quiser criar um editor? Vamos ter de usar outra API: mais tempo, mais esforços duplicados, e assim vai.

GStreamer

Repetindo: GStreamer é um framework para desenvolvimento de aplicações de fluxo multimídia. Vamos falar do "fluxo de multimídia" mais à frente, por hora observe a figura a seguir que nos apresenta uma visão que, embora grosseira, nos dará uma noção inicial de onde se posiciona o GStreamer no esquema das coisas.

GStreamer provê uma camada de abstração sobre componentes de manipulação para qualquer formato para o qual haja um plugin instalado. As aplicações não precisam mais se preocupar em implementar decodificadores, mixers, sincronia nem codecs, podem se concentrar apenas nas "funcionalidades legais para o usuário", o que significa aplicações melhores e mais pessoas felizes. :)

GStreamer também é multiplataforma, já tendo sido avistado no Linux x86, PPC, ARM, Solaris x86 e SPARC, MacOSX, Microsoft Windows e IBM OS/400.

Veja uma lista das funcionalidades em: http://gstreamer.freedesktop.org/features

Na Terra dos Usuários: "Não me importo, apenas abra meus arquivos!"

Sobre o exemplo do início do artigo, o problema de sincronia do Totem, que fazia muitos instalarem o totem-xine (Totem com bibliotecas do Xine), existia até a versão 0.8 do GStreamer e era devido bugs na sincronia de threads, esse e vários outros foram sanados com o lançamento da série 0.10[3]. Depois do lançamento desta série muitas aplicações multimídia começaram a usar o GStreamer como infra-estrutura.

Algumas aplicações:

E a lista cresce rápido.[4] Além disso, GStremer é usado no Nokia 770[5] e na nova plataforma da Palm[6]

Lembrando que o GStreamer é um projeto do Freedesktop[7], e foi pensado para ser o mais neutro possível, podendo ser usado por qualquer Desktop (inclusive, roda no Windows), com licenças escolhidas para evitar questões legais, bem comuns quando se está lidando com codecs multimídia proprietários, e dar o máximo de liberdade para os desenvolvedores. O próprio GStreamer está sob a LGPL, embora alguns plugins e codecs estejam sob uma licença BSD.

Antes de nos aprofundarmos (mas só um pouco) na arquitetura do GStreamer, aqui estão instruções sobre como instalar todos os codecs num Debian/Ubuntu. Para outras distribuições confira nos seus repositórios, para quem gosta de compilar, os fontes estão em

É bem simples: vá no Synaptic (ou apt-get ou aptitude) e instale todos os pacotes que começarem com gstreamer0.10, exceto os que terminarem com -dbg, esses são para debug, e se quiser a documentação (que é excelente), pode instalar os que terminarem com -doc. E não esqueça de adicionar os repositórios Universe e Multiverse no Ubuntu e Non-Free no Debian.

Devido a quantidade de plugins e de dúvidas sobre licenciamento levantadas por algumas distribuições, os plugins do GStreamer foram divididos em:

  • gst-plugins-base: conjunto estável de plugins provendo algumas funcionalidades básicas.
  • gst-plugins-good: boa qualidade, funcionamento correto e licença LGPL.
  • gst-plugins-ugly: boa qualidade e funcionamento correto, mas suas licenças impõem problemas sobre a distribuição.
  • gst-plugins-bad: não tão bons, alguns não são mantidos (algum voluntário?).

Lembrando que os problemas de licenciamento sobre alguns codecs, como mp3 e avi, são o motivo de várias distribuições não poderem vir com suporte a estes formatos. O que não impede que o usuário baixe por si próprio, não contando como distribuição.

Fundamentos do GStreamer Elementar

Como prometi, vamos falar do tal fluxo de mídia (media stream). Pense na passagem de tempo de uma música que você está ouvindo, num filme que está assistindo ou mesmo na sua vida - trata-se de um fluxo, como a corrente de um rio. No GStreamer tudo começa com a fonte (source) do fluxo de mídia, que pode ser qualquer coisa: um arquivo, áudio de um microfone, um streaming da internet, etc. O fluxo proveniente desta fonte é recebido por um consumidor (sink): outro arquivo, uma tela, fones de ouvido. Todo fluxo precisa de uma fonte e um ponto término. Filosofia pura. Um diagrama ajudará na compreensão:

Elementos

Na nomenclatura do GStreamer cada componente, exceto o fluxo, é um Elemento, e este deve ter pelo menos um source, um sink, os dois, ou vários de cada um. Elementos podem estar em quatro estados:

  • Null: estado padrão.
  • Ready: buffers são alocados e arquivos abertos, mas o fluxo está na espera.
  • Paused: o fluxo está aberto, mas seu "movimento" está congelado.
  • Playing: igual a Paused, mas os dados estão fluindo.

Filtros

No meio do caminho do fluxo para seu destino, pode haver elementos que recebem o fluxo em seu sink, fazem alguma manipulação, e entregam o resultado em seu source. Estes elementos são chamados de filtros, e normalmente vários deles são necessários.

Pads

Sources e sinks são chamados conjuntamente de pads, que são as "portas" por onde passa o fluxo. Eles possuem capacidades de manipulação de dados bem específicas e podem restringir o tipo de dados que pode passar por eles. Se você quiser processar um fluxo de mp3 precisará dos elementos certos (que já vêm com os pads adequados) para lidar com os dados. Os pads também fornecem informações sobre suas capacidades para elementos que queiram se conectar a eles. A figura a seguir mostra pads source específicos para áudio e vídeo de um demuxer (separador de canais).

Existem três tipos de pads:

  • Dinâmicos: aparecem e desaparecem conforme a necessidade; se, por exemplo, o demux do exemplo anterior fosse para um stream OGG, apresentaria os pads de acordo com o conteúdo: áudio, vídeo ou ambos.
  • Request: pads criados sob demanda.
  • Ghost pads: bú!

Bin

É simplesmente um container de elementos. Do lado esquedo do Bin da ilustração a seguir, aparece um pad sink ligado ao sink do "elemento1". Este sink pad é chamado ghost pad e é um tipo de link simbólico para o sink do "elemento1". Utilizando ghost pads e o fato dos Bins poderem receber instruções de mudança de estado (Playing, Pause, etc.), podemos tratá-los como elementos comuns e integrá-los em fluxos de mais alto nível, abstraindo detalhes complicados.

Um tipo especial de Bin é chamado Pipeline. Trata-se de da Bin de mais alto nível, que contém todos os elementos e outros Bins do... pipeline. Hmmm, isso ficou feio. Quis dizer, chamamos um sistema completo de Pipeline, eu digo que "monto um Pipeline" para transformar WAV em OGG, OGG em MP3, para extrair o áudio de um DivX, etc.

Bus

Segundo o manual, é um sistema de transferência de mensagens entre as threads de um pipeline. A desenvolvedor da aplicação não precisa criar a Bus, que é criada pelo pipeline, nem se preocupar com threads, apenas definir um handler para as mensagens que chegarem do pipeline. Funciona como um tipo de callback, mas polling também é possível.

Buffers e Eventos

Rapidinho esse aqui. Buffers guardam os dados do fluxo no pipeline, Eventos contém informação de controle.

E esses são os componentes de um Pipeline (que agora sabemos o nome). Quem lida com desenvolvimento de hardware (alô pessoal de Engenharia!) deve ter notado a semelhança com os termos e componentes usados no desenvolvimento de sistemas eletrônicos.

Plugins

O que são? São codecs? São elementos? Codecs são elementos? Mais ou menos. Se eu quiser exorcisar um vídeo WMV para OGG, vou precisar de elementos adequados para entender estes formatos, portanto podemos dizer que elementos são codecs. Plugin é a "embalagem" na qual elementos (que podem ser codecs) são disponibilizados, eles são blocos de código que podem ser carregados, como um objeto compartilhado (shared object, .so), que os escravos do Egito, digo usuários do Windows chamam de DLL. Um plugin pode disponibilizar um ou mais elementos e encapsula toda informação sobre os mesmos.

Pitfdll

Este é um plugin especial. Caso não exista um codec livre/aberto para o formado que você quer tocar/abrir/converter, Pitfdll[8] é capaz de carregar arquivos binários DLL (DirectShow) e QTX (QuickTime). Mais informações aqui[9] e aqui[10]. Fiz isso no 0.8 e nem lembro se funcionou, acho que sim. Não recomendo codecs binários do windows, deixem como última solução.

Alguma Prática, Por Misericórdia

Todas estas informações são necessárias não só para entender o funcionamento do GStreamer, como para criar aplicações que usem todo esse poder de fogo. Agora somos capazes de criar pipelines! Podemos escrever um programa que use GStreamer e montar um pipeline com objetos, ou montá-lo com aplicações gráficas como gst-editor, ou usar o gst-launch. Esta ferramenta é instalada junto com o GStreamer, ela serve para montar pipelines na linha de comando, possibilitando a criação de scripts para, por exemplo, converter toda uma coleção de MOVs para OGG/Theora. Os elementos são conectados através de sinais de exclamação ("!"), que cumprem o mesmo papel dos tradicionais pipes ("|") do shell Unix.

Os exemplos foram tirados das man pages do gst-launch, o nome exato do comando vai depender da versão do GStreamer, usaremos gst-launch-0.10. Se você instalou todos os plugins tudo deve funcionar legal.

Tocar um arquivo mp3

 $ gst-launch-0.10 filesrc location="weezer - hit me baby one more time (britney cover).mp3" ! mad ! audioconvert ! audioresample ! osssink 
Deixando a conexão como PAUSADA ... A conexão está fazendo PREROLL ... A conexão teve feito o PREROLL ... Deixando a conexão em TOCANDO ... New clock: audioclock0

Depois que a música acabar, rolarão as seguintes mensagens:

 Obtido EOS do elemento "pipeline0".
 Execution ended after 213340055000 ns.
 Deixando a conexão como PAUSADA ...
 Deixando a conexão em PRONTA ...
 Deixando a conexão em NULL ...
 LIBERANDO a conexão ...

Diagrama do Pipeline:

Como mostra o diagrama, o fluxo de mídia começa no elemento filesrc, que introduz o conteúdo do arquivo indicado no pipeline; mad[11] é um elemento dos plugins Ugly e decodifica mp3. audioconvert e audioresample são elementos dos plugins básicos, seus nome são sugestivos, e pra escapar de explicar digo que "mais detalhes podem ser vistos em [12]"; também testei sem audioresample e funcionou legal (gst-launch-0.10 filesrc location="weezer - hit me baby one more time (britney cover).mp3" ! mad ! audioconvert ! osssink), mas sem audioconvert nada feito, com direito a mensagem:

ATENÇÃO: conexão errônea: não foi possível ligar mad0 a osssink0

Segundo a documentação do pacote de plugins ugly[13]:

Audioconvert
converte buffers de áudio "cru" (raw) entre vários formatos possíveis. Ele suporta conversão de inteiro para float, sinal e endianness.

E o osssink manda o som pras caixas.

Tocar um arquivo Ogg

Vá em http://commons.wikimedia.org/wiki/Image:Frase_de_Neil_Armstrong.ogg e vamos ouvir Neil Armstrong dizendo "a small step for a man, a great step for cinlug". Sério! Confiram:

 $ gst-launch-0.10 filesrc location="Frase_de_Neil_Armstrong.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! osssink

É parecido com o anterior, exceto que no lugar de mad, colocamos oggdemux e vorbisdec. Ogg é apenas um container para dados codificados que podem vir em forma de áudio, vídeo ou texto (legendas), daí a necessidade de um demux para separar os canais; vorbisdec decodifica o fluxo saído de oggdemux e manda para caixa de som (osssink).

Converter arquivo mp3 para Ogg/Vorbis

 $ gst-launch-0.10 filesrc location="weezer - hit me baby one more time (britney cover).mp3" !  mad ! audioconvert ! vorbisenc ! oggmux ! filesink location="weezer-hitmebaby.ogg"

Para testar:

 $ gst-launch-0.10 filesrc location="weezer-hitmebaby.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! osssink

Tocando Vídeo Ogg/Theora e Canal de Áudio Vorbis

Peque o vídeo (licenciado pela Creative Commons) "A New Computer" em http://www.polycrystal.org/lego/movies.html (link rápido: http://www.polycrystal.org/lego/movies/A_New_Computer--small.ogg). No pipeline a seguir, identificamos o demux ogg com o nome "d" (name=d) e dizemos que uma seqüência de elementos se conecta a ele usando a notação "d.". Antes de se confundir com o código, atentai para o diagrama.

 $ gst-launch-0.10 filesrc location="A_New_Computer--small.ogg" ! oggdemux name=d d. ! queue ! theoradec ! ffmpegcolorspace ! ximagesink d. ! queue ! vorbisdec ! audioconvert ! audioresample ! osssink

O elemento queue força o uso de threads separadas para os canais de vídeo e áudio, ffmpegcolorspace converte vídeos de um colorspace para outro, e ximagesink é um consumidor de vídeo padrão para o Servidor X.

Faça você mesmo

Agora mesmo você está pensando "como vou saber que componentes usar para minha mídia?". Não se aflija, mas também não fique esperando! Para fazer ser próprio pipeline para filtrar seus fluxos de mídia do jeito que quiser, você deve conhecer os elementos disponíveis. Como foi mencionado antes, os elementos vêm em pacotes de plugins, e estes possuem uma documentação onde cada elemento é explicado, de forma que você pode escolher o que melhor se adequar. Veja a documentação online em:

GStreamer Core Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/
GStreamer Base Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/
GStreamer Good Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/
GStreamer Bad Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/
GStreamer Ugly Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-ugly-plugins/html/
GStreamer FFMPeg Plugins
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-ffmpeg-plugins/html/

Gst-editor

Existe uma ferramenta gráfica para criação de uso de pipelines, basta incuir elementos e ligá-los com o mouse.

A figura mostra um pipeline adequado para tocar DVD e enviar seu áudio para saída de som do computador e para um arquivo.

Esta versão do gst-editor foi escrita em C e usa o GStreamer 0.8. Um dos projetos do Summer of Code do Google consiste em criar uma versão mais nova do gst-editor para o 0.10. Esta versão será escrita em Python com PyGTK, e deverá dispor seus componentes num Canvas baseado no Cairo, o Goocanvas[14]. (Baixei o demo; muito interessante.) O blog do GSTEditor está em http://gsteditor.wordpress.com

Conclusão

Espero que tenha sido proveitoso e que você entenda a idéia por trás do GStreamer e como ele pode servir como sólida base para aplicações multimídia. Agora você pode converter e tocar seus arquivos de mídia.

Para mais possibilidades do gst-launch, veja:

O site oficial é uma das melhores fontes de informação sobre o GStreamer, destaco os documentos:

GStreamer Application Development Manual
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html
GStreamer Plugin Writer's Guide
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/

No próximo artigo, programação com Python e GStreamer.

Referências

[1] http://groups.google.com/group/cinlug/browse_thread/thread/99fcdaa268e636a9/53528a6f6d6275d8
[2] http://gstreamer.freedesktop.org
[3] http://gstreamer.freedesktop.org/documentation/gstreamer010.html
[4] http://gstreamer.freedesktop.org/apps
[5] http://www.maemo.org/platform/docs/multimedia/multimedia_architecture.html
[6] http://www.linuxdevices.com/news/NS4663700447.html
[7] http://www.freedesktop.org/wiki
[8] http://ronald.bitfreak.net/pitfdll.php
[9] http://www.ubuntuforums.org/showthread.php?t=165325
[10] http://www.ubuntuforums.org/showthread.php?t=31214
[11] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-ugly-plugins/html/gst-plugins-ugly-plugins-plugin-mad.html
[12] http://gstreamer.freedesktop.org/data/doc/gstreamer/0.10.6/gst-plugins-base-plugins/htm/ch01.html
[13] http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-ugly-plugins
[14] http://www.dachaplin.dsl.pipex.com/goocanvas


Autor: Marcelo Lira


Atribuição-Compatilhamento pela mesma licença 2.5