Vitor Medina Cruz
Ginga-NCL para Dispositivos Portáteis
Dissertação de Mestrado
Dissertação apresentada como requisito parcial para obtenção do título de Mestre pelo Programa de Pós-Graduação em Informática da PUC-Rio.
Orientador: Prof. Luiz Fernando Gomes Soares
Rio de Janeiro
Junho de 2008
Vitor Medina Cruz
Ginga-NCL para Dispositivos Portáteis
Dissertação apresentada como requisito parcial para obtenção do título de Mestre pelo Programa de Pós-Graduação em Informática da PUC-Rio. Aprovada pela Comissão Examinadora abaixo assinada.
Luiz Fernando Gomes Soares Orientador
PUC-Rio
Guido Lemos de Souza Filho UFPB
Renato Fontoura de Gusmão Cerqueira PUC-Rio
José Eugenio Leal Coordenador(a) Setorial do Centro Técnico Científico - PUC-Rio
Rio de Janeiro, 13 de junho de 2008
Todos os direitos reservados. É proibida a reprodução total ou parcial do trabalho sem autorização da universidade, do autor e do orientador.
Vitor Medina Cruz
Recebeu seu título de Bacharel em Informática pela Pontifícia Universidade Católica do Rio de Janeiro (PUC-Rio) em 2005. Atualmente integra o grupo de pesquisadores do Laboratório TeleMídia da PUC-Rio, desenvolvendo pesquisa na área de Sistemas Hipermídia.
Ficha Catalográfica
Cruz, Vitor Medina
Ginga-NCL para Dispositivos Portáteis / Vitor Medina
Cruz ; orientador: Luiz Fernando Gomes Soares. - 2008.
84 f. ; 29,7 cm
Dissertação (mestrado) – Pontifícia Universidade
Católica do Rio de Janeiro, Rio de Janeiro, 2008.
Inclui referências bibliográficas.
1. Informática – Teses. 2. Middleware Declarativo. 3.
TV Digital. 4. Ginga-NCL. 5. SBTVD. 6. NCL I. Soares, Luiz
Fernando Gomes. II. Pontifícia Universidade Católica do
Rio de Janeiro. Departamento de Informática. III. Título.
CDD: 004
Este trabalho é dedicado aos meus pais, Alice e João.
Agradecimentos
Primeiramente ao meu orientador, o professor Luiz Fernando Gomes Soares,
pela sua dedicação em me orientar, pela sua paciência e pelo seu esforço em
fazer com que eu me superasse.
Em especial, ao Marcio Moreno pela sua disposição em me ajudar, pelos
ensinamentos, pelas dicas, enfim, por todo o auxílio oferecido que foi
fundamental na concepção deste trabalho.
Ao Carlão, ao Felipe Nogueira, ao Rafael Savignon e ao Francisco pela ajuda
oferecida. Ao Felipe Bittencourt pelo auxílio na criação das aplicações NCL.
A todos do TeleMidia pela amizade e pelo companheirismo oferecidos ao longo
desse período em que trabalhamos juntos. Esses também foram fatores muito
importantes na realização deste trabalho.
Agradeço também a minha namorada, Vilani, pelos momentos de descontração
e pela compreensão nas horas mais difíceis.
À minha família, meus pais (Alice e João) e minha irmã (Helena), pelo apoio e
auxílio oferecidos, que tornaram possível a minha chegada até aqui. Agradeço
também aos meus amigos do n-eto, pela amizade sincera e pelo incentivo.
Aos membros da banca, pelos comentários e sugestões.
A todos os funcionários do Departamento de Informática da PUC-Rio.
Por fim, agradeço à CAPES e ao Laboratório TeleMidia pelo auxílio financeiro,
fundamental para a realização deste trabalho.
Resumo
Cruz, Vitor Medina; Soares, Luiz Fernando Gomes. Ginga-NCL para Dispositivos Portáteis. Rio de Janeiro, 2008. 84p. Dissertação de Mestrado - Departamento de Informática, Pontifícia Universidade Católica do Rio de Janeiro.
O advento da TV Digital traz muitas vantagens, como a melhora da
imagem, do som e o suporte à interatividade. Um sistema de TV Digital
especifica técnicas de codificação e transmissão de conteúdos televisivos a
serem transmitidos das emissoras para os dispositivos receptores dos
telespectadores. Um elemento importante definido por tais sistemas é o
middleware. No contexto da TV Digital, o middleware oferece uma linguagem de
programação a ser usada na criação das aplicações interativas. O middleware
especificado pelo Sistema Brasileiro de TV Digital (SBTVD), denominado Ginga,
é composto por dois ambientes: um declarativo, o Ginga-NCL, e outro
imperativo, o Ginga-J. Apenas o uso do Ginga-NCL é obrigatório nos dispositivos
portáteis. Dentre as vantagens do Ginga-NCL, ressalta-se o fato da sua
linguagem, a NCL, apresentar um conjunto de características que são
adequadas para a criação de conteúdo televisivo interativo. É importante,
entretanto, realizar uma implementação de referência do Ginga-NCL que sirva
como prova de conceito da especificação, ou seja, que mostre a sua viabilidade
de uso na prática. Este trabalho apresenta a primeira implementação de
referência do Ginga-NCL para dispositivos portáteis, baseada na sua
implementação de referência para os terminais fixos. Entre as plataformas
estudadas, a do sistema operacional Symbian foi escolhida para a realização da
implementação proposta, por apresentar as maiores vantagens. Os problemas
encontrados durante o desenvolvimento da implementação proposta são
apresentados juntamente com as soluções dadas. Ao final, testes sistêmicos
foram usados na identificação e correção de erros da implementação resultante
deste trabalho.
Palavras-chave middleware, Ginga-NCL, SBTVD, portátil, NCL, TVD.
Abstract
Cruz, Vitor Medina; Soares, Luiz Fernando Gomes (Advisor). Ginga-NCL for Portable Devices. Rio de Janeiro, 2008. 84p. Master Thesis - Departamento de Informática, Pontifícia Universidade Católica do Rio de Janeiro.
The advent of the Digital TV brings many advantages, such as image and
sound improvement and interactivity support. A Digital TV system defines
codification and transmission techniques for content to be transmitted from
broadcasters to receiver devices belonging to viewers. An important element
defined for such systems is the middleware. In the Digital TV context, the
middleware provides a programming language to be used on the creation of
interactive applications. The middleware specified by the Sistema Brasileiro de
TV Digital (SBTVD), known as Ginga, is composed by two environments: one
declarative, the Ginga-NCL, and another imperative, the Ginga-J. Only Ginga-
NCL is mandatory in portable devices. Among the advantages of Ginga-NCL,
stands out the fact of its language, the NCL, has a set of characteristics that are
suitable for creation of interactive television content. However, it is important to
make a Ginga-NCL reference implementation that can be used as proof of
concept of the specification, which shows its use viability in practice. This work
presents the first Ginga-NCL reference implementation for portable devices,
based upon its reference implementation for fixed terminals. Among the studied
platforms, the one provided by Symbian operating system was chosen to carry
out the proposed implementation, since it has the greatest benefits. The
problems found during the development of the proposed implementation are
presented together with the solutions given. At the end, systemic tests were used
on the identification and correction of errors of the implementation resulted from
this work.
Key words middleware, Ginga-NCL, SBTVD, portable, NCL, DTV.
Sumário
1 Introdução 10
2 Estado da Arte 12
2.1. A TV Digital e os Dispositivos Portáteis 12
2.2. Middlewares 14
2.3. Sistemas Operacionais e suas Plataformas 18
3 Implementação 23
3.1. A implementação de referência para terminais fixos 23
3.2. Symbian C++, a API Base e a STL 27
3.3. Parser do Documento NCL 31
3.4. O Uso de Threads 39
3.5. Active Objects 42
3.6. O Tratamento de Âncoras Temporais 47
3.7. Exibidores no Symbian C++ 51
3.8. Considerações Finais 56
4 Testes Sistêmicos 60
4.1. Formula 1 60
4.2. Matrix 63
4.3. Carnaval 66
4.4. Exibidor HTML com Canal de Retorno 69
5 Conclusões e Trabalhos Futuros 73
6 Referências Bibliográficas 77
Apêndice A – Instalação e Dispositivos Testados 80
Lista de figuras
Figura 1: Camada de Serviço Específico do Ginga. Retirado
adaptado de (Soares, Rodrigues e Moreno, 2007). 24
Figura 2: Núcleo Comum do Ginga. Retirado e adaptado de
(Soares, Rodrigues e Moreno, 2007). 24
Figura 3: Exemplo simples de uma aplicação NCL. 33
Figura 4: Documento NCL como uma árvore. 34
Figura 5: Diagrama de Classes da estrutura usada para
resolver o problema das dependências entre tags. 37
Figura 6: Exemplo de um documento NCL com âncoras
temporais. 48
Figura 7: Exemplo de fila de tempos definidos em âncoras
temporais. 49
Figura 8: Acesso das camadas de abstração dos exibidores
e do Display do dispositivo por parte da máquina de
apresentação. 53
Figura 9: Aplicação Fórmula1. 61
Figura 10: Os três casos de interação da aplicação Fórmula1. 62
Figura 11: Aplicação Matrix_Mobile. 64
Figura 12: Primeiro caso de sincronismo da aplicação
Matrix_Mobile. 64
Figura 13: Segundo caso de sincronismo da aplicação
Matrix_Mobile (Sem interação). 65
Figura 14: Segundo caso de sincronismo da aplicação
Matrix_Mobile (Com interação). 65
Figura 15: Aplicação Carnaval. 66
Figura 16: Aplicação Carnaval com legenda e com as duas
opções de interação. 67
Figura 17: Os dois casos de interação da aplicação Carnaval. 68
Figura 18: Aplicação 4. 69
Figura 19: Seleção e uso da página HTML. 70
Figura 20: Botão pressionado. 71
1 Introdução
Um sistema de TV Digital especifica técnicas de codificação e transmissão
de conteúdos de TV como vídeo, áudio e dados que serão transmitidos das
emissoras para os dispositivos receptores pertencentes aos telespectadores. Um
elemento importante definido por um sistema desses é o middleware.
O middleware, no contexto da TV Digital, é responsável por oferecer uma
linguagem de programação a ser usada na criação das aplicações interativas, e
por tornar independentes as características particulares de um sistema
operacional e do hardware do dispositivo receptor. Um middleware pode definir
uma linguagem declarativa, imperativa ou ambas.
Atualmente, existem muitos sistemas de TV Digital sendo usados e
padrões de middleware definidos ou ainda em fase de desenvolvimento. No
Brasil, a Era da TV Digital está apenas começando, com a transmissão do sinal
sendo feita tanto para terminais fixos como para dispositivos portáteis. Essa
nova Era vem com inúmeras vantagens, donde se destacam a melhoria da
qualidade da imagem e do som. Entretanto, a possibilidade de interatividade na
TV é uma característica que representa, de maneira mais explícita, a
convergência digital. Ela oferece dinamismo e abre um novo leque de opções de
produtos e serviços que podem ser oferecidos pela TV. Assim, verifica-se a
grande importância de um middleware em um sistema de TV Digital, pois é
através dele que se provê o suporte à interatividade.
Para os receptores, ou terminais de acesso, o Sistema Brasileiro de TV
Digital (SBTVD) por difusão terrestre especifica como opcional a implementação
de um middleware. Entretanto, toda implementação existente deve seguir as
especificações do middleware Ginga. Existem dois ambientes definidos nesse
middleware: um declarativo, o Ginga-NCL, e outro imperativo, o Ginga-J. Para
terminais fixos, ambos são requeridos, mas, para o escopo dos dispositivos
portáteis, apenas o Ginga-NCL é obrigatório.
Para demonstrar que a especificação do Ginga-NCL é viável na prática, ou
seja, que o seu uso é adequado tanto nos terminais fixos quanto nos dispositivos
portáteis, é importante realizar uma implementação de referência em ambas as
plataformas que sirva como prova de conceito da especificação. Implementações
Introdução 11
de referência e comerciais do middleware Ginga-NCL já existem no universo dos
terminais fixos, contudo isso ainda não era uma realidade para o caso dos
dispositivos portáteis. O principal objetivo deste trabalho é, portanto, apresentar
a primeira implementação de referência do Ginga-NCL para os dispositivos
portáteis que o valide, ou seja, que demonstre a adequação desse middleware
nos dispositivos portáteis. Procura-se ressaltar, também, os problemas
constatados e as soluções encontradas durante o processo de desenvolvimento.
Isso é feito com o intuito de permitir que os resultados apresentados nesta
dissertação possam ser usados como referência em implementações futuras do
Ginga-NCL desenvolvidas para outras plataformas portáteis.
Para fazer a implementação proposta, entretanto, foi necessário estar
atento às características e limitações diferenciais encontradas nos dispositivos
portáteis. Normalmente, a quantidade de recursos disponíveis nesse tipo de
aparelho, principalmente a de memória, é bem inferior àquela encontrada nos
terminais fixos. Também foi necessário estudar o estado da arte da TV Digital,
em especial para o contexto dos dispositivos portáteis. Um estudo comparativo
dos middlewares existentes também foi realizado, sempre com o foco no escopo
dos dispositivos portáteis, a fim de salientar a importância do Ginga-NCL.
Também foi feita uma análise dos sistemas operacionais e das suas plataformas
de desenvolvimento projetadas para os dispositivos portáteis. A partir disso, foi
possível escolher a melhor opção para a implementação de referência feita e
apresentada nesta dissertação.
No Capítulo 2 é apresentado um resumo desses estudos, que são
detalhados em (Cruz, Moreno e Soares, 2008), levando em consideração os
pontos mais relevantes para o objetivo aqui proposto. O Capítulo 3 se dedica à
implementação realizada, expondo os problemas encontrados com suas
respectivas soluções. O Capítulo 4 apresenta os testes realizados na
implementação proposta. Já o Capítulo 5 traz algumas considerações finais
sobre o trabalho desenvolvido e apresenta uma discussão acerca de possíveis
trabalhos futuros. O Apêndice A apresenta os detalhes sobre a instalação da
solução desenvolvida, bem como trata do seu uso nos dispositivos portáteis.
2 Estado da Arte
Este capítulo tem como objetivo apresentar, de forma sucinta, o estado
atual da TV Digital para dispositivos portáteis. A Seção 2.1 trata da TV Digital e
dos dispositivos portáteis. A Seção 2.2 aborda os middlewares declarativos
existentes, dando enfoque àqueles mais adequados ao contexto da TV Digital
para dispositivos portáteis. Finalmente, a Seção 2.3 tece algumas considerações
acerca dos sistemas operacionais e das plataformas de desenvolvimento
existentes no escopo dos dispositivos portáteis. Um estudo mais detalhado sobre
esses pontos pode ser encontrado em (Cruz, Moreno e Soares, 2008).
2.1. A TV Digital e os Dispositivos Portáteis
A TV Digital possibilita uma grande melhora na qualidade da imagem e do
som dos programas ou conteúdos exibidos. Isso ocorre, dentre outros fatores,
por conta da natureza da transmissão digital, que possui métodos muito mais
precisos de recuperação da informação recebida se comparados aos da
transmissão analógica. Dessa forma, as perdas na qualidade da imagem
geradas por imprecisões ocorridas na transmissão são muito mais fáceis de
serem compensadas em um sistema de TV Digital. Uma outra vantagem é que,
sendo de natureza digital, o conteúdo oferecido pode ser comprimido, reduzindo
a taxa de bits gerada. Isso possibilita a sua transmissão em uma banda de
freqüência menor do que a utilizada pela TV analógica. O fato do conteúdo ser
de natureza digital também viabiliza seu armazenamento e o uso de funções de
PVR (Personal Video Recoder), como pause e rewind, mesmo em programas
sendo exibidos ao vivo. Com relação à redução de banda necessária, o mesmo
canal de freqüência hoje utilizado por uma transmissão analógica será capaz de
transmitir mais de um fluxo de áudio e de vídeo, além dos fluxos de dados. O
vídeo transmitido poderá possuir a definição SDTV (Standard Definition TV),
conforme utilizado na transmissão analógica, ou ainda HDTV (High Definition
TV), que oferece uma qualidade de imagem superior.
Estado da Arte 13
A transmissão de outros dados, além do áudio principal e do vídeo
principal, permite o envio de aplicativos que possibilitam ao telespectador
interagir com o programa que está sendo exibido. Também é possível oferecer
conteúdos personalizados e mais adequados às necessidades do telespectador,
o que pode contribuir, ainda, para uma mudança no modelo de negócios hoje
usado.
“A TV Digital pode ser provida trazendo-se tecnologias computacionais
para o âmbito da TV ou levando as tecnologias de TV para o ambiente
computacional.” (Cruz, Moreno e Soares, 2008: 2).
No primeiro caso, enquadram-se, de maneira geral, as transmissões de TV
Digital por radiodifusão terrestre, cabo ou satélite. Este modelo permite a
disponibilização da TV Digital com interatividade e personalização do conteúdo.
Se for adicionada alguma tecnologia de canal de retorno, também será possível
oferecer serviços de conteúdo sobre demanda. Esse tipo de serviço permite ao
telespectador escolher um programa de um acervo fornecido pela emissora para
ser assistido na hora que lhe for mais conveniente, e também torna viável à
emissora obter um melhor conhecimento dos seus usuários.
No caso em que a tecnologia de TV é levada ao ambiente computacional,
temos a IPTV (TV over IP), onde o conteúdo televisivo é distribuído através do
protocolo da Internet IP (Internet Protocol). O uso da IPTV é feito, normalmente,
em redes fechadas, como em TVs por assinatura, e encontra-se mais próximo
do modelo da Internet. Com o uso dessa tecnologia é possível disponibilizar a
TV Digital com interatividade, personalização e serviços de conteúdo sobre
demanda. Por outro lado, serviços de broadcast, normais em transmissões de
TV, não são providos naturalmente com o uso do protocolo IP, onde serviços
bidirecionais de unicast são mais comuns. Isso força a utilização da técnica de
multicasting, pela qual a transmissão é feita de um para n endereços IP’s
registrados em um grupo, chamado de grupo multicast. Um problema associado
a isso seria a complexidade da rede envolvida, que pode acabar aumentando
muito. Uma maior discussão sobre as possibilidades da TV Digital é apresentada
em (Cruz, Moreno e Soares, 2008: 1).
No caso da aplicação da TV Digital nos dispositivos portáteis, é preciso
ficar atento às características diferenciais encontradas nesses aparelhos, das
quais é possível citar:
“• Uso de bateria, que exige um consumo moderado de energia. Aplicações nesse escopo podem ser sumariamente terminadas, e precisam se adequar ao fato. Um outro ponto é que o consumo de energia gerado pela aplicação precisa ser baixo;
Estado da Arte 14
• Limite de processamento e de memória; • Mobilidade, com processo de handoff; • Tamanho de tela pequeno; • A conversa, no caso do celular, como funcionalidade principal. Qualquer
outra atividade fica em segundo plano; • Teclado limitado; • Limite maior de banda. ” (Cruz, Moreno e Soares, 2008: 4) Os sistemas de TV Digital e seus middlewares precisam se adaptar a
essas características a fim de possibilitarem a recepção dos conteúdos digitais
nos dispositivos portáteis. Entretanto, os esforços nesse sentido iniciaram-se há
pouco tempo e ainda não são muitos. Um exemplo é o caso do Japão, país
avançado em termos de TV Digital, que começou a migração desse serviço para
os dispositivos portáteis apenas em meados de 2006.
2.2. Middlewares
“Middleware é uma camada intermediária entre o hardware/SO e as
aplicações” (Cruz, Moreno e Soares, 2008: 18) que tem por finalidade facilitar o
desenvolvimento das suas aplicações e torná-las independentes da plataforma
de hardware e do sistema operacional do aparelho receptor. (Cruz, Moreno e
Soares, 2008), no Capítulo 6, estuda vários sistemas de TV Digital encontrados
na literatura e os seus respectivos middlewares. Foi feita, ainda, uma análise
comparativa entre os vários middlewares, com o objetivo de determinar quais
seriam as melhores opções para o escopo dos dispositivos portáteis. Esta seção
apresenta, de forma resumida, esse estudo e as suas conclusões.
Em IPTV, não existe qualquer padrão de middleware definido. Hoje, o que
mais se vê são soluções proprietárias, altamente especializadas e,
freqüentemente, completamente fechadas. No que diz respeito ao uso dessa
tecnologia em dispositivos portáteis, existe menos definição ainda. As soluções
proprietárias (Cruz, Moreno e Soares, 2008: 52-63) fazem nenhuma ou pouca
menção ao uso nesses dispositivos. Mesmo a pequena movimentação de
padronização existente na área de IPTV não chega a tocar nesse assunto com
profundidade. Sendo assim, não parece existir, em IPTV, qualquer solução
interessante para a disponibilização da TV Digital em dispositivos portáteis.
Por outro lado, a TV Digital por radiodifusão terrestre, cabo ou satélite
possui padrões de sistemas de TV Digital abertos e implementados, que são
apresentados, com os seus respectivos middlewares, em (Cruz, Moreno e
Estado da Arte 15
Soares, 2008: 18-51). Os mais relevantes são apresentados aqui de forma
resumida, ao mesmo tempo em que é feita a avaliação de seus usos nos
dispositivos portáteis.
O MHP (Multimedia Home Plataform), desenvolvido pelo fórum DVB
(Digital Video Broadcast), não foi desenvolvido para o ambiente dos dispositivos
portáteis. Sua especificação baseia-se no J2SE (Java 2 Standard Edition), que é
uma plataforma de desenvolvimento Java feita para terminais fixos. Como
descrito em (Cruz, Moreno e Soares, 2008: 12-16), J2SE não é adequado para
ser usado em dispositivos portáteis com limitações de recursos. Além disso, o
próprio DVB define um padrão de transmissão de TV Digital para esse tipo de
aparelho, o DVB-H (Digital Video Broadcast - Handheld), que não determina o
uso do MHP. Esse middleware parece ser, portanto, inadequado para o escopo
dos dispositivos portáteis. Mais detalhes acerca deste middleware podem ser
encontrados em (Cruz, Moreno e Soares, 2008: 18-24).
O sistema de TV Digital ACAP (Advanced Common Application Platform),
criado pelo comitê internacional ATSC (Advanced Television Systems
Committee), não é apropriado para a transmissão de TV Digital em dispositivos
portáteis por conta do seu padrão de modulação, o 8-VSB. Como é detalhado
em (Digital TV Facts, 2006), o 8-VSB não atende os requisitos mínimos
necessários para a transmissão adequada aos dispositivos portáteis, que é feita
sem o uso de cabos. O middleware do sistema ACAP não é implementado em
nenhum aparelho desse tipo. Mais informações desse sistema de TV Digital
podem ser encontradas em (Cruz, Moreno e Soares, 2008: 30).
O middleware DIMS (Dynamic and Interactive Multimedia Scenes),
desenvolvido por uma organização internacional de padronização na área de
telecomunicações, denominada 3GPP (3rd Generation Partnership Project), foi
especificado para ser usado no padrão de transmissão do sistema de TV Digital
MBMS (Mobile Broadcast/Multicast Service). Esse middleware foi desenvolvido
especificamente para os dispositivos portáteis. Apesar disso, a sua especificação
ainda se encontra em fase de “drafting” e com pouco conteúdo definido, sendo
que boa parte dele ainda é muito superficial. Dessa forma, o DIMS também pode
ser descartado, hoje, como uma opção de middleware para dispositivos
portáteis. Um estudo mais aprofundado desse middleware e do seu respectivo
sistema de TV Digital é encontrado em (Cruz, Moreno e Soares, 2008: 44-46).
O LASeR (Lightweight Application Scene Representation) é um padrão de
middleware da ISO (International Organization for Standardization) desenvolvido
com o objetivo de substituir o MPEG4 BIFS (Binary Format for Scene) que não
Estado da Arte 16
se mostra adequado para o ambiente dos dispositivos portáteis. LASeR foi
desenvolvido especificamente para esse tipo de aparelho e é um superset do
SVG Tiny (Scalable Vector Graphics - Tiny), que, por sua vez, é uma linguagem
declarativa do W3C, desenvolvida para dispositivos com limitações de recursos.
A especificação LASeR define, além da linguagem declarativa, dois tipos de
linguagens de script: o application/ecmascript e o application/laserscript. O
primeiro deriva do SGV, que define uma linguagem de script baseada no
ECMAScript, e o segundo é usado em aplicações LASeR a fim de executar
ações de edição ao vivo. Mais detalhes sobre esse middleware podem ser
conferidos em (Cruz, Moreno e Soares, 2008: 40-44). Apesar de se apresentar,
aparentemente, como um bom middleware de TV Digital para dispositivos
portáteis, o LASeR não possui qualquer implementação sua sendo usada ou
mesmo de referência, além da sua especificação ainda não estar totalmente
finalizada.
HisTV é um padrão de middleware desenvolvido especificamente para
dispositivos portáteis que usam o DVB-H na recepção de conteúdo. Foi criado
pela GMIT, uma empresa de consultoria relacionada ao padrão DVB-H, mas é,
atualmente, suportado por outras instituições. A sua especificação já está bem
adiantada e já existem alguns produtos da Siemens e da Benq com sua
implementação, como pode ser visto em (Cruz, Moreno e Soares, 2008: 40).
O desenvolvimento de uma aplicação HisTV deve ser feito através de um
processo de três etapas: “a construção do layout da tela, o projeto da máquina
de estados e a produção dos objetos.” (Cruz, Moreno e Soares, 2008: 37). A
construção do layout deve ser feita com o uso de objetos espaciais predispostos
na tela, os ifields. São dois os tipos de layout: o landscape (320x204) e o portrait
(240x320). A aplicação deve ser desenvolvida considerando-se ambos. Pode-se
perceber, portanto, que a arrumação dos objetos na tela é limitada aos ifields
disponíveis e aos modos de layout.
O próximo passo no desenvolvimento de uma aplicação é a construção de
uma máquina de estados que será usada na apresentação da aplicação HisTV.
Essa máquina deve ser concebida com cuidado, pois o procedimento é bem
complexo.
A produção do conteúdo consiste na edição dos nomes dos arquivos que
representam os objetos de mídia, levando-se em conta os ifields e os estados da
máquina de estados relacionados a esses objetos. Esse procedimento é,
aparentemente, muito complexo, confuso e trabalhoso. A especificação cita,
entretanto, a existência de um script perl que gera automaticamente os arquivos
Estado da Arte 17
corretamente nomeados. Isso é feito recebendo como entrada um arquivo no
formato .csv, contendo informações sobre a máquina de estados, as mídias e os
ifields. O uso desse script, entretanto, não é muito claro, assim como também
não é claro como o arquivo no formato .csv deve ser criado. Detalhes em
minúcias sobre o HisTV podem ser vistos em (Cruz, Moreno e Soares, 2008: 36-
40).
O HisTV tem como vantagem o fato de ter sido especificado para o
ambiente dos dispositivos portáteis e de já possuir implementações da sua
especificação executando nesse tipo de aparelho. Entretanto, o seu domínio de
aplicações é pequeno por conta da sua interface fixa. Comparado aos outros
middlewares que serão apresentados, o seu maior problema é, contudo, o fato
da autoria das suas aplicações ser muito complicada, o que certamente
inviabiliza a criação de aplicações por pessoas leigas.
A BML (Broadcast Markup Language) é parte integrante do middleware do
padrão de TV Digital Japonês, o ISDB-T. A linguagem baseia-se, com algumas
adaptações e adições, na XHTML 1.0 e possui uma curva de aprendizagem
pequena. A BML possui também elementos imperativos especificados com uma
linguagem de script baseada no ECMAScript. O foco do middleware BML é na
apresentação do documento e na interação com o usuário. Nas aplicações de
TV Digital, entretanto, o sincronismo e a adaptabilidade são fatores tão ou mais
importantes, conforme (Moreno, 2006). A BML é adequada à transmissão para
dispositivos fixos ou portáteis, definindo perfis da linguagem que são mais
adequados a cada um dos dois casos. No Japão, já existem implementações
comerciais desse middleware para terminais fixos e dispositivos portáteis.
A BML é o único middleware apresentado até agora que possui
especificação finalizada com implementações nos dispositivos portáteis, e que é
simples o suficiente de ser usada. Em (Cruz, Moreno e Soares, 2008: 30-36),
podem ser encontradas mais informações sobre a BML.
O Ginga-NCL faz parte do Sistema Brasileiro de TV Digital (SBTVD). Esse
sistema define dois ambientes para seu middleware: um ambiente declarativo
(Ginga-NCL) e um ambiente imperativo (Ginga-J). Esta dissertação se concentra
no Ginga-NCL, por ser o único ambiente obrigatório no perfil portátil. A
linguagem usada por esse middleware é a NCL (Nested Context Language), que
define dois perfis: um avançado, o Enhanced Language Profile, e um outro mais
básico, o Basic Language Profile. A linguagem de script especificada para a NCL
é a linguagem Lua. O Ginga-NCL possui uma curva de aprendizagem mais alta
que a BML, mas, quando aprendida, é mais simples de ser usada. Ela se
Estado da Arte 18
distingue da BML especialmente por ter o seu foco no sincronismo, em sua
forma geral, e na adaptabilidade. Em (Cruz, Moreno e Soares, 2008: 25-28),
podem ser encontradas mais informações sobre o Ginga-NCL.
Dentre os middlewares apresentados, a BML e o Ginga-NCL parecem ser,
atualmente, os mais relevantes para o escopo dos dispositivos portáteis. (Cruz,
Moreno e Soares, 2008: 62-64) oferece mais detalhes sobre essa conclusão,
bem como apresenta uma análise comparativa entre os middlewares aqui
resumidos.
Ainda que se apresente como uma boa opção de middleware para os
dispositivos portáteis, faltava ao Ginga-NCL uma implementação de referência
para esse tipo de dispositivo que demonstrasse o seu uso na prática, o que foi
realizado e está sendo apresentado nesta dissertação.
2.3. Sistemas Operacionais e suas Plataformas
No escopo dos dispositivos portáteis, encontramos Sistemas Operacionais
feitos justamente para atender as características diferenciais desses aparelhos.
Um desses sistemas teve que ser escolhido para a realização da implementação
de referência do Ginga-NCL proposta nesta dissertação. Um estudo desses
Sistemas Operacionais e das suas plataformas de desenvolvimento foi feito e
apresentado em (Cruz, Moreno e Soares, 2008: 5-18) com o objetivo de levantar
todas as opções existentes e permitir a escolha de uma delas. Nesse estudo,
deu-se preferência a sistemas com plataforma aberta, estáveis, de baixo custo,
com boa quantidade de dispositivos disponíveis para teste no mercado, que
sejam usados hoje e que possam representar uma opção viável de uso no
mercado futuro. Esta seção apresenta um resumo desse estudo realizado, onde
foram analisados cinco sistemas operacionais: Symbian, Linux, Windows,
PalmOS e BlackBerry.
O BlackBerry possui pouca participação no mercado, não apresentando
tendências de crescimento. É fechado e não é distribuído em dispositivos que
não tenham sido desenvolvidos pela sua fabricante, a RIM (Research In Motion).
Sendo assim, o BlackBerry foi desconsiderado para uma implementação de
referência do Ginga-NCL. O mesmo pode-se dizer do PalmOS, que não possui
nenhuma das suas versões sendo substancialmente utilizada. Ao invés disso, a
Palm, criadora do PalmOS, tem investido na criação de um novo sistema, o
Estado da Arte 19
ACCESS Linux Platform (ACL), baseado no Linux, com o objetivo de tentar obter
uma participação maior no mercado. Isso, entretanto, acaba por exaltar mais o
valor da plataforma Linux em detrimento do sistema PalmOS propriamente dito.
O Windows Mobile é baseado na conhecida e muito usada plataforma
Windows. Uma grande vantagem desse sistema é que o desenvolvimento das
suas aplicações pode ser feito com as mesmas ferramentas usadas na versão
do Windows para desktop. Por outro lado, os mesmos problemas encontrados
na versão desktop, como reinicializações de sistema e vazamentos de memória,
também são encontrados no Windows Mobile. Um outro problema são os custos
elevados atrelados à plataforma, discutidos com mais detalhes em (Cruz,
Moreno e Soares, 2008: 6-7). Um último problema é a bem conhecida existência
de vírus na plataforma Windows.
Sistemas Linux para dispositivos portáteis têm surgido por conta do
crescimento desse mercado. “O Linux é um sistema flexível que oferece uma
grande diversidade de métodos de instalação e, por conta disso, pode funcionar
em muitos sistemas heterogêneos. Uma grande vantagem do seu uso nos
dispositivos portáteis é que, se for configurado corretamente, o consumo de
recursos pode ser reduzido em muito.” (Cruz, Moreno e Soares, 2008: 7). Outra
vantagem é o porte de uma aplicação de uma plataforma Linux fixa para uma
portátil — exige-se, aparentemente, apenas que essa última possuísse a sua
disposição todas as bibliotecas requeridas pela aplicação.
Apesar dessas vantagens, a configuração desse sistema é, normalmente,
uma tarefa complicada. Um outro problema reside nas distribuições mais
estáveis do Linux, que para dispositivos portáteis são pagas. Isso adiciona um
problema de custo. Entretanto, o Linux possui uma plataforma aberta e a maioria
das suas ferramentas de desenvolvimento pode ser usada sem qualquer custo.
O Linux foi um forte candidato para o desenvolvimento do middleware de
TV Digital proposto neste estudo, isso por contar com uma plataforma aberta,
robustez, flexibilidade, baixo custo e perspectiva de crescimento no segmento
dos dispositivos portáteis. O desenvolvimento do middleware ainda seria
favorecido pelo fato da implementação de referência para receptores fixos ter
sido desenvolvida para esse sistema operacional. Entretanto, devido a pouca
quantidade de distribuições existentes e estáveis, a falta de informação acerca
das configurações exigidas e das bibliotecas disponíveis, além dos poucos
dispositivos que vem com o sistema instalado, a sua utilização foi descartada.
O Symbian é um sistema operacional feito especificamente para
dispositivos portáteis. É robusto e se encontra no mercado desde 1998. Foi feito
Estado da Arte 20
com o objetivo de ser econômico no consumo de recursos, em especial a
memória e a bateria. É, também, o mais usado, possui plataforma aberta e as
aplicações podem ser desenvolvidas em uma série de tecnologias diferentes,
como Symbian C++, Java e Flash. Uma lista completa dessas tecnologias pode
ser encontrada em (Cruz, Moreno e Soares, 2008: 5). Symbian também é o
único sistema que oferece uma versão, a 9.5, com suporte à TV Digital. Por ser
muito utilizada, a plataforma em questão está sujeita a vírus, mas, em razão
disso, novas versões oferecendo mais segurança já foram lançadas e já são
utilizadas. Embora tenha muitas vantagens, os altos custos atrelados à
plataforma constituem um problema. O sistema em si não é gratuito e as
ferramentas de desenvolvimento gratuitas possuem recursos limitados.
O Symbian possui uma vasta comunidade, muitas opções de
desenvolvimento, muitos dispositivos no mercado com o sistema instalado e é o
único que possui uma versão para TV Digital. A sua ferramenta de
desenvolvimento gratuita, apesar de apresentar limitações, é estável, e a
plataforma como um todo parece ser robusta. Apesar dos custos associados, o
Symbian foi considerado a melhor opção para uma primeira implementação do
Ginga-NCL para dispositivos portáteis. Em (Cruz, Moreno e Soares, 2008: 8-9),
essa conclusão é apresentada juntamente com uma análise mais detalhada de
todos os sistemas aqui apresentados.
Uma vez tendo escolhido o sistema, é necessário optar por uma das suas
plataformas de desenvolvimento. Um estudo abrangente foi feito em (Cruz,
Moreno e Soares, 2008: 9-18) sobre as duas principais plataformas do Symbian:
a plataforma nativa do Symbian OS e a plataforma JavaME (Java Micro ou
Mobile Edition).
Na plataforma nativa do Symbian OS, a linguagem Symbian C++, que é
baseada na linguagem C++, é usada no desenvolvimento das aplicações.
Symbian C++ é uma linguagem complexa, mas ela permite ao programador ter
mais controle sobre o código da sua aplicação, facilitando, com isso, a criação
de otimizações mais refinadas. O poder de expressão da linguagem Symbian
C++ também é muito elevado, o que permite ao programador desenvolver tanto
aplicações simples quanto complexas (Symbian Ltd, 2007a). Uma outra
vantagem a ser considerada é que realizar o desenvolvimento na plataforma
nativa do Symbian OS implica na possibilidade do uso direto de API’s nativas do
sistemas, que são muito otimizadas. O desenvolvimento nessa plataforma
também permite ao programador ter acesso completo aos recursos de hardware.
Todos esses são fatores importantes e requeridos na implementação de um
Estado da Arte 21
middleware de TV Digital. Maiores detalhes sobre a plataforma nativa do sistema
operacional Symbian são discutidos em (Cruz, Moreno e Soares, 2008: 10-12).
A plataforma JavaME (Micro ou Mobile Edition), por sua vez, é um
subconjunto da J2SE (Java Technology, 2007) e foi desenvolvida para atender
aos requisitos dos dispositivos portáteis e móveis de pequeno a grande porte. A
plataforma JavaME oferece uma linguagem simples de desenvolvimento que é
bem conhecida, a Java, e oferece uma portabilidade que, na prática, não existe.
A linguagem de programação Java é simples de ser usada, mas, por conta
disso, ela remove parte do controle que o programador tem sobre o código da
sua aplicação, impossibilitando-o de realizar otimizações mais refinadas.
Entretanto, o maior fator negativo contra a JavaME é a impossibilidade de
acesso aos recursos de hardware por meio da sua linguagem. Toda
funcionalidade existente no dispositivo deve ser acessada através de uma API
JavaME, que, quando não existe, inviabiliza o uso da funcionalidade em questão.
No que diz respeito à TV Digital, a comunidade Java ainda está preparando a
JSR 272, uma API Java que oferecerá suporte às funcionalidades de TV Digital.
Quando a especificação em questão estiver terminada, novos aparelhos com a
sua API precisarão ser lançados antes que novas aplicações que façam uso
dessa API possam ser desenvolvidas. Maiores detalhes sobre a plataforma
JavaME são discutidos em (Cruz, Moreno e Soares, 2008: 12-16).
O que se pôde concluir é que a plataforma nativa do Symbian OS reúne
todas as características necessárias para o desenvolvimento do middleware
Ginga-NCL para dispositivos portáteis, enquanto que as limitações do JavaME
inviabilizam esse projeto. Portanto, para o objetivo proposto, optou-se pela
plataforma de desenvolvimento do Symbian OS. Essa resolução e uma análise
mais detalhada dessas duas plataformas são apresentadas em (Cruz, Moreno e
Soares, 2008: 17-18).
Nessa plataforma, é preciso, ainda, escolher uma UI (User Interface) de
desenvolvimento. As UIs determinam as características específicas do sistema
Symbian, e são associadas às famílias de dispositivos. Como exemplo, tem-se o
S60 Symbian SDK (Software Development Kit), usado para implementar
aplicações compatíveis com a família de dispositivos S60 da Nokia. Na
implementação do Ginga-NCL para dispositivos portáteis, foi dada prioridade ao
uso de API’s Symbian genéricas. Entretanto, parte da implementação é
necessariamente específica a uma UI.
A UI escolhida foi a S60, com o SDK que oferece suporte a versão 9.2 do
sistema operacional Symbian, a mais recente disponibilizada para
Estado da Arte 22
desenvolvimento. Essa escolha foi feita devido à disponibilidade de
documentação, a uma ampla comunidade que oferece suporte ao
desenvolvimento e à grande quantidade de dispositivos Nokia S60 disponíveis
no mercado, o que possibilitaria testes em dispositivos com mais facilidade e
rapidez. Neste trabalho, quando qualquer API for descrita, ela será sempre
genérica, a não ser que o contrário seja dito.
3 Implementação
Este capítulo apresenta a implementação do Ginga-NCL para dispositivos
portáteis, baseada no perfil Basic DTV da linguagem NCL. Sua implementação
foi baseada na implementação de referência do Ginga-NCL para dispositivos
fixos, que é descrita resumidamente na Seção 3.1 desta dissertação. Da Seção
3.2 em diante, são analisados os problemas surgidos na nova implementação,
as soluções oferecidas e as principais diferenças entre a implementação de
referência para dispositivos fixos e a que está sendo apresentada nesta
dissertação. A Seção 3.2 apresenta as API’s básicas da plataforma Symbian
C++, sua similaridade com a linguagem C++ e sua incompatibilidade com a
biblioteca STL (Standard Template Library). A Seção 3.3 descreve os desafios
superados na modificação do procedimento de parser do documento NCL para a
versão portátil. A Seção 3.4 trata do uso e da necessidade da substituição da
implementação da thread POSIX (Portable Operating System Interface for
UNIX) por um outro recurso mais apropriado à plataforma Symbian C++, o Active
Object, descrito na Seção 3.5. A Seção 3.6 explica como e por que o tratamento
de âncoras temporais teve que ser alterado. A Seção 3.7 apresenta os
exibidores de mídia com suporte no Symbian e o desafio de implementá-los, a
fim de substituírem aqueles usados na implementação de referência para
dispositivos fixos do Ginga-NCL. Por fim, a seção 3.8 tece algumas
considerações finais acerca da implementação apresentada.
3.1. A implementação de referência para terminais fixos
A implementação de referência do Ginga-NCL para terminais fixos foi
desenvolvida em C++ para plataformas que utilizam o sistema operacional Linux.
A Figura 1 e a Figura 2 ilustram a arquitetura do middleware Ginga.
Na Figura 1, a camada de serviço específico é apresentada. É possível
observar a divisão do Ginga no ambiente declarativo Ginga-NCL, que
corresponde à máquina de apresentação, e no ambiente procedural Ginga-J,
Implementação 24
que corresponde à máquina de execução. Nesta dissertação, como já foi dito,
apenas o Ginga-NCL é abordado, pois é o único ambiente obrigatório em
receptores portáteis. Os módulos mais importantes da máquina de apresentação
são o Conversor e o Gerenciador de Exibidores, que estão representados na
Figura 1.
Figura 1: Camada de Serviço Específico do Ginga. Retirado adaptado de (Soares,
Rodrigues e Moreno, 2007).
A Figura 2, por sua vez, apresenta a camada de núcleo comum da
arquitetura Ginga. Essa camada possui módulos que servem tanto para o Ginga-
NCL quanto para o Ginga-J, ou seja, ambas as máquinas fazem uso dessa
camada. Os módulos mais importantes, representados na figura, são: Exibidores
de Mídia, ou simplesmente Exibidores, Gerenciador do Módulo de Apresentação,
Sintonizador, Filtro de Seções e Processador de Fluxos de Dados.
Figura 2: Núcleo Comum do Ginga. Retirado e adaptado de (Soares, Rodrigues e
Moreno, 2007).
A máquina de apresentação é responsável por controlar a execução das
aplicações NCL. A implementação dessa máquina, assim como a
implementação do middleware como um todo, foi feita em C++ utilizando a STL a
std lib e API’s POSIX. Um documento NCL, descrevendo uma aplicação, deve
ser processado pela máquina de apresentação antes que o controle da aplicação
propriamente dita possa ser realizado.
Implementação 25
Por ser uma aplicação XML, o processamento de um documento NCL se
inicia pelo emprego de um parser XML. O módulo Conversor, que faz parte da
máquina de apresentação, é responsável justamente por fazer esse
processamento, traduzindo o documento NCL recebido da emissora, ou de
qualquer outra fonte, em uma estrutura baseada no modelo NCM (Nested
Context Model) (SOARES et all, 2003), o modelo conceitual da linguagem NCL.
A partir dessa estrutura, a máquina de apresentação cria um modelo de
execução que é, então, usado no controle da aplicação NCL. O módulo
conversor foi implementado com base no framework para parsers DOM
(Document Object Model) especificado em (Silva, Rodrigues e Soares, 2005) e
fazendo uso da biblioteca libxerces-c, que implementa um parser DOM para
documentos XML.
Uma vez tendo o modelo de execução montado, a máquina de
apresentação inicia a apresentação da aplicação NCL. Para realizar a exibição
das mídias da aplicação NCL em execução, a máquina de apresentação faz uso
dos exibidores, ou objetos de execução. Os objetos de execução, pertencentes
ao módulo Exibidores da Figura 2, são responsáveis por tratar as diferentes
mídias que podem ser usadas em uma aplicação NCL. Os exibidores abstraem o
uso das API’s de mídia, que são específicas de plataforma, contribuindo para
que o funcionamento da máquina de apresentação seja independente de
plataforma. Existe um exibidor para cada tipo de mídia diferente e fica a cargo do
Gerenciador de Exibidores, um outro módulo da máquina de apresentação,
realizar a instanciação desses elementos. Uma vez instanciados, os conteúdos a
serem exibidos devem ser apresentados em uma determinada região da tela do
dispositivo em que a aplicação NCL está sendo executada, de acordo com a
especificação da aplicação.
Cabe à máquina de apresentação determinar em qual região um exibidor
associado a uma mídia qualquer deve ser instanciado. Em outras palavras, é de
responsabilidade da máquina de apresentação o controle das regiões definidas
em uma aplicação NCL e a associação dos exibidores a essas regiões.
Para fazer o acesso à tela do dispositivo, a máquina de apresentação faz
uso do Gerenciador do Módulo de Apresentação. Tal gerenciador abstrai o
acesso das possíveis camadas gráficas definidas pelo sistema de TV Digital e
ainda o uso das API’s de acesso à tela do dispositivo, que são específicas de
plataforma. Essa abstração feita pelo Gerenciador do Módulo de Apresentação
também contribui, assim, para que o funcionamento da máquina de
apresentação seja independente de plataforma. O acesso às regiões da tela,
Implementação 26
bem como sua manipulação, é feita pelo Gerenciador do Módulo de
Apresentação através da biblioteca DirectFB (directfb.org | Main, 2008).
Diversas bibliotecas são utilizadas pelo módulo Exibidores. A
decodificação por software de vídeos e de qualquer outro tipo de mídia contínua
é feita com o uso da libxine. Imagens png, jpg, gif, tiff e bmp, são tratadas pelas
bibliotecas libpng, libjpeg e libtiff. Por fim, documentos HTML são tratados pela
telemidia-links. Mais informações sobre os exibidores e o acesso às camadas
gráficas são encontradas em (Moreno, 2006: 74-81) e em (Moreno, 2006: 82-84).
Os módulos da camada Núcleo Comum usados na recepção de dados
pelo fluxo de transporte (TS — transport stream), são o Sintonizador, o Filtro de
Seções e o Processador de Fluxo de Dados.
O módulo Sintonizador permite que a máquina de apresentação sintonize
em um canal específico com o objetivo de receber um fluxo de transporte
enviado pela emissora. Informações mais detalhadas desse módulo podem ser
encontradas em (Moreno, 2006: 66-69). O fluxo de transporte enviado pela
emissora pode, por sua vez, transportar, ao mesmo tempo que o vídeo e o aúdio
principal de um programa, dados diversos. Dados no formato de estrutura de
sistema de arquivos são transportados pelo carrossel de objetos DSM-CC em
seções privadas DSM-CC, conceito discutido com detalhes em (Moreno,
2006:22-32). O módulo Filtro de Seções é usado com o objetivo de filtrar as
seções do fluxo de transporte, conforme detalhado em (Moreno, 2006: 69-70).
O módulo Processador de Fluxo de Dados, por sua vez, é usado no
tratamento do protocolo DSM-CC que, entre outras funcionalidades, define o
funcionamento do carrossel de objetos, usado na transmissão cíclica de dados
(Moreno, 2006). O mesmo módulo é responsável por lidar também com eventos
de fluxo, que também fazem parte do protocolo DSM-CC. Mais detalhes acerca
desse protocolo e do Processador de Fluxo de Dados podem ser encontrados,
respectivamente, em (Moreno, 2006: 32-39) e (Moreno, 2006: 70-74).
Dos elementos apresentados resumidamente nesta seção, a máquina de
apresentação, o Gerenciador de Exibidores, o Conversor, o modulo Exibidores e
o Gerenciador do Módulo de Apresentação foram implementados na versão do
Ginga-NCL para dispositivos portáteis. As especificidades dessa implementação
são apresentadas nas seções seguintes.
Como os receptores disponíveis no mercado não dispunham de recepção
na modulação SBTVD-T (modulação ISDB), os módulos Sintonizador, Filtro de
Seções e Processador de Fluxo de Dados — usados no tratamento do fluxo de
transporte — não foram implementados, ficando como trabalhos futuros a serem
Implementação 27
realizados. Para a simulação de funcionamento, programas de TV pré-
armazenados no dispositivos foram utilizados.
3.2. Symbian C++, a API Base e a STL
O desenvolvimento de aplicações na plataforma do Symbian OS é feito
com o uso da linguagem Symbian C++, que, por sua vez, é baseada na
linguagem C++. Symbian C++ possui uma série de API’s, mas a mais básica
delas é a API Base (Symbian Ltd, Nokia, 2006), como indica o próprio nome. A
linguagem Symbian C++ e a API Base possuem algumas diferenças da
linguagem C++ e das API’s básicas usadas na implementação de referência do
Ginga-NCL para dispositivos fixos. Essas diferenças tiveram que ser tratadas
com cuidado na implementação do Ginga-NCL para dispositivos portáteis. Esta
seção apresenta, primeiramente, as principais diferenças da linguagem Symbian
C++ e sua API Base para a linguagem C++ e suas API’s básicas. Em seguida,
apresenta como essas diferenças foram tratadas na atual implementação.
Um recurso comum muito utilizado na linguagem C++ são as exceções. O
uso de exceções em Symbian C++ não era suportado inicialmente (Morley,
2007). Ao invés delas, o uso de recursos nativos da plataforma Symbian, os
Leaves e as TRAPS (Symbian Ltd, Nokia, 2006), era a solução oferecida pela
linguagem. Posteriormente, as exceções passaram a ser suportadas e até
mesmo recomendadas por consumirem menos ciclos de CPU que os Leaves e
TRAPS, e por serem compatíveis com o padrão da linguagem C++. Entretanto,
existem algumas diferenças na implementação desse recurso no Symbian por
conta do seu consumo de memória.
Cada exceção exige a alocação de um espaço de memória e, na
linguagem C++, mais de uma exceção pode ser lançada ao mesmo tempo. Essa
ação, chamada de lançamento aninhado de exceções, pode ocorrer quando uma
exceção é lançada no destrutor de um objeto qualquer, como é explicado em
(Morley, 2007). Como o lançamento de exceções em destrutores é algo
plausível, torna-se impossível saber o quanto de memória uma aplicação
precisará alocar para permitir o uso de exceções. Se, no entanto, o lançamento
aninhado de exceções nunca ocorrer, ou seja, se exceções nunca forem
lançadas em destrutores de objetos, é garantido que o espaço de memória
necessário seja exatamente o de uma única exceção.
Implementação 28
Como a alocação do espaço de memória poderia ser proibitivo se mais de
uma exceção fosse lançada ao mesmo tempo, Symbian C++ proíbe o
lançamento aninhado de exceções. Quando isso acontece, a aplicação que o fez
é simplesmente abortada. Isso garante a necessidade de uma única alocação de
memória para o uso de exceções ao longo de toda a vida do programa. Sendo
assim, existe a necessidade de se remover quaisquer lançamentos aninhados de
exceções de códigos portados para a plataforma Symbian. Essa resolução e
mais detalhes sobre o uso de exceções em Symbian são encontrados em
(Morley, 2007).
Felizmente, a implementação de referência do Ginga-NCL para
dispositivos fixos faz pouco uso de exceções, e que nunca são lançadas de
forma aninhada. Assim, o uso desse recurso não precisou ser modificado na
implementação para dispositivos portáteis. Chama-se a atenção, no entanto,
para o problema, quando do porte de outras implementações Ginga-NCL que
possam vir a fazer uso de exceções aninhadas.
O tratamento de exceções foi a única diferença encontrada entre a
linguagem Symbian C++ e a C++. Problemas maiores são vistos no uso da API
Base do Symbian OS com o objetivo de se substituir as API’s básicas usadas na
implementação de referência do Ginga-NCL.
A API Base do Symbian possui as estruturas mais simples que podem ser
usadas na implementação de uma aplicação qualquer. Nessa API, todos os tipos
básicos encontrados na linguagem C++ são redefinidos. Muitos desses tipos
são, na verdade, meras re-declarações. Como exemplo, tem-se o TInt, um tipo
definido pela API Base, que é, na verdade, um typedef para o tipo básico
signed int. A afirmação é verdadeira para todos os tipos básicos integrais e,
portanto, nesses casos, é seguro fazer uso desses tipos diretamente. Nos
demais casos, como o do TChar, substituto do char, são definidas novas classes
na API Base, sendo o uso delas recomendado, mas não obrigatório, nem crítico.
A recomendação de uso desses tipos específicos do Symbian serve mais para
forçar os programadores a manterem uma padronização no código do que para
aumentar a sua eficiência. Ou seja, essa recomendação não precisa ser seguida
para fins de porte.
Com base nas afirmações do parágrafo anterior, todos os tipos básicos
usados na implementação de referência do Ginga-NCL para dispositivos fixos,
tanto na máquina de apresentação como em outros módulos, não foram
mapeados em tipos Symbian C++, ou seja, o porte foi feito de forma direta. Por
Implementação 29
outro lado, todo o código novo inserido na implementação fez uso exclusivo da
API Base.
A implementação para dispositivos fixos do Ginga-NCL faz uso de
strings, threads e mutexes, além de outras API’s std lib e POSIX. Isso sim
causou, de fato, um problema de porte, uma vez que a API Base tem a sua
própria definição para esses elementos, que são incompatíveis com aqueles da
std lib e do POSIX.
Para o problema mencionado no parágrafo anterior, foram criados o
P.I.P.S. (P.I.P.S. Is Posix on Symbian) e o Open C. A Symbian Ltd, a pedido da
comunidade de desenvolvimento Symbian, iniciou o desenvolvimento do P.I.P.S.
com o objetivo de facilitar o porte de aplicações desenvolvidas em C/C++. Essa
biblioteca, entretanto, não cobre todas as API’s POSIX nem toda a std lib. Em
decorrência, a Nokia desenvolveu o Open C, um superset do P.I.P.S. para o
S60, cuja implementação cobre um pouco mais o oferecido pelas API’s POSIX e
a std lib, mas não ainda a sua totalidade. Maiores informações sobre o
percentual das bibliotecas implementadas pelo P.I.P.S. e Open C podem ser
encontradas em (Forum Nokia, 2007: 6).
Felizmente, na implementação do Ginga-NCL para dispositivos portáteis, o
P.I.P.S. e o Open C cobriram o uso de todas as funcionalidades requeridas, o
que inclui strings, threads e mutexes. A Seção 3.4 desta dissertação
demonstra, entretanto, que o uso de threads não pôde ser mantido na
implementação do Ginga-NCL para dispositivos portáteis.
A implementação de referência do Ginga-NCL para dispositivos fixos
também faz muito uso de outros elementos complexos, como vetores, conjuntos
e listas, lançando mão da API STL. O problema aqui é que a API Base define
novas classes para esses elementos, que são completamente diferentes
daquelas definidas na STL.
Uma solução para esse problema foi criar um mapeamento próprio das
classes STL utilizadas na implementação de referência do Ginga-NCL para
classes correspondentes da API Base. Como as classes da STL e da Base são
muito diferentes entre si, tendo, normalmente, assinaturas de métodos muito
distintas, o mapeamento proposto tornou-se muito difícil. No caso da classe STL
map, não existe nem mesmo uma classe correspondente no Symbian que
pudesse ser usada de forma adequada. A classe mais próxima da map definida
pela API Base é a TBTreeFix<Chave, Valor> (Symbian Ltd, Nokia, 2006), que
usa uma árvore B para armazenar Valores relacionados às suas respectivas
Chaves. Contudo, essa API possui uma forte restrição, pois Valor e Chave
Implementação 30
devem sempre possuir um tamanho fixo em bytes. Isso significa que todas as
Chaves inseridas em um objeto TBTreeFix devem possuir um tamanho fixo igual
a X, e que todos os Valores inseridos devem ter tamanho fixo igual a Y, onde X e
Y são quaisquer números em bytes. Isso tornou a substituição da map pela
TBTreeFix inoportuna, uma vez que os objetos usados pela implementação
possuem tamanhos indefinidos. Seria necessário definir tamanhos máximos para
todos os objetos e garantir que todos tivessem exatamente esses valores,
mesmo que precisassem, na prática, ocupar espaços menores.
Uma opção muito mais simples foi implementar uma map própria, criando
duas listas, uma para armazenar as Chaves e a outra para armazenar os
Valores. As duas listas ficam relacionadas entre si e são ordenadas
crescentemente por ordem de Chave. A solução proposta não causa gasto
desnecessário de memória, fator importante no escopo dos dispositivos
portáteis, e o tempo de busca por um elemento na lista não é substancial, uma
ver que o uso das maps no Ginga-NCL é bem simples e com poucas entradas. A
criação dessa map específica resolveu, portanto, o problema da
incompatibilidade da classe map STL com a plataforma Symbian de forma
eficiente.
Uma outra incompatibilidade encontrada foi no uso de iterators. Esse é
um recurso provido pela STL usado para realizar interações em estruturas de
lista. Esse recurso, entretanto, simplesmente não existe na API Base do
Symbian. Diferentemente do caso das maps, a solução para esse problema foi
substituir todas as ocorrências encontradas de uso de iterators por um outro
procedimento de interação sobre listas equivalente.
Essa solução de mapeamento foi usada em uma parcela da
implementação do Ginga-NCL para dispositivos portáteis com sucesso, mas
demonstrou-se muito problemática. Se toda a implementação do Ginga-NCL
fosse feita com o uso dessa solução de mapeamento, boa parcela do código
original teria que ser desnecessariamente modificada. Isso poderia introduzir
erros que, depois, seriam de difícil remoção.
Outros programadores da comunidade Symbian também experimentaram
o mesmo problema e, tendo consciência disso, a Symbian Ltd começou a
implementar um porte da STL para o sistema operacional Symbian. Todavia,
essa implementação ainda não havia terminado quando o desenvolvimento do
Ginga-NCL para dispositivos portáteis foi iniciado. Dessa forma, ou mantinha-se
a solução do mapeamento das API’s já descrita, o que consumiria muito tempo e
poderia gerar erros, ou tentava-se realizar, por conta própria, o porte de alguma
Implementação 31
implementação STL existente para o Symbian. Essa última opção poderia
também consumir muito tempo. Além disso, a implementação STL escolhida
para o porte teria que ter sido desenvolvida com a preocupação no uso de
recursos, caso contrário, a implementação do Ginga-NCL poderia ficar muito
pesada para ser executada nos dispositivos portáteis.
Um dos membros da comunidade Symbian, entretanto, fez um porte
eficiente de uma implementação STL para o Symbian. Essa implementação é a
STLPort (STLPort, 2001), que foi desenvolvida em ANSI C++ de maneira
otimizada, visando ao máximo a eficiência. Com essas características, a API
STL em questão pode ser portada para plataformas embarcadas ou com
restrições de recursos sem muitos problemas. O porte dessa API para o
Symbian pode ser obtido em (Jez, 2007). A sua instalação e uso são simples,
bastando apenas fazer a referência correta aos headers e ligar estaticamente a
única biblioteca necessária, a stlport_s.lib. Feito isso, o código com referências a
STL compila e executa normalmente. Não foi observada nenhuma degradação
do sistema devido ao uso dessa biblioteca. Sendo assim, a solução para o
problema da STL foi considerado resolvido com o uso desse porte, tendo sido
abandonada por completo a solução de mapeamento descrita.
3.3. Parser do Documento NCL
É possível enumerar dois tipos de parser XML: o SAX (Simple API for
XML) e o DOM (Document Object Model) parser.
O primeiro oferece uma API simples e eficiente para o tratamento de
documentos XML. O SAX percorre todo o documento apenas uma vez e, durante
esse processo, lança eventos. Esses eventos indicam o início de uma tag, o fim
dela, o início ou o fim de um documento como um todo, dentre outras ações.
Para utilizar o SAX, uma aplicação precisa implementar funções que recebam e
tratem esses eventos. Essas funções, quando chamadas, são supridas de todas
as informações necessárias, como os atributos de uma tag. Por conta desse
modelo, o SAX possui uma API leve, principalmente em termos de consumo de
memória, pois, uma vez que o evento foi tratado, nada mais referente a ele fica
alocado. O problema no uso dessa API é o fato do desenvolvimento tornar-se
mais complicado. Não é possível, por exemplo, obter dados sobre uma tag que
já foi tratada. Assim, se uma aplicação precisa de informações do XML em
Implementação 32
diferentes momentos, ou se precisa adicionar alguma informação ao documento,
o SAX pode não ser uma boa opção.
O DOM parser, por sua vez, monta um modelo de árvore em memória a
partir de um documento XML qualquer. Esse modelo é como qualquer outro
objeto, podendo ser alterado e usado sem grandes dificuldades. Por outro lado,
como o DOM armazena e mantém o modelo em memória, usá-lo em dispositivos
que possuem restrições de recursos não é muito indicado.
Estudos comparativos entre DOM e SAX são feitos em (Violleau, 2002),
(Oren, 2002), (Devsphere, 2007) e (Franklin, 2007). Foram feitos testes
empíricos de desempenho em relação ao consumo de memória e de
processador nesses estudos, e os resultados demonstram a superioridade do
SAX nesses aspectos. Entretanto, mesmo com as vantagens do SAX, a versão
original do Conversor desenvolvida para a implementação de referência do
Ginga-NCL em dispositivos fixos, descrito no Item 3.1, foi feita com o uso do
DOM parser.
A natureza do Ginga-NCL aparentemente não exige que sejam feitos
muitos acessos ao documento NCL, e qualquer alteração que precise ser feita
na aplicação pode ser aplicada diretamente no seu modelo NCM associado.
Essas características do Ginga-NCL fazem com que o uso do DOM parser não
seja necessário. Em especial, levando-se em consideração que o estudo desta
dissertação lida com dispositivos que possuem limitações de recursos, o uso do
DOM parser torna-se oneroso. A Symbian e a própria comunidade de
desenvolvimento recomendam sempre o uso do SAX para a realização do parser
de documentos XML em dispositivos portáteis. Assim, dada a evidência da falta
de necessidade do uso do DOM parser, do seu gasto elevado de recursos e das
recomendações da Symbian, o seu uso no módulo Conversor foi substituído pelo
parser SAX na implementação do Ginga-NCL para dispositivos portáteis.
Sabe-se que o módulo Conversor da implementação de referência
realizava o parser do documento NCL fazendo uso de um framework para
parsers DOM especificado em (Silva, Rodrigues e Soares). Esse framework teve
que ser estudado para que o funcionamento do módulo em questão pudesse ser
reformulado a fim de se remover as particularidades existentes do parser DOM.
Por outro lado, a parte específica do Ginga-NCL, que cria a estrutura NCM, foi
mantida e adaptada para funcionar com o parser SAX. Essa adaptação gerou,
para cada tag presente na linguagem NCL, uma função específica que cria o
elemento NCM correspondente.
Implementação 33
No Symbian, a API que realiza o parser de documentos XML não é
genérica. No caso da plataforma S60, essa API se resume à classe CParser, um
parser SAX de documentos XML. Para ser iniciado, o parser SAX em questão
recebe o documento XML, no caso um documento NCL, e o analisa do início até
o fim em busca de tags. Quando o parser descobre a existência de uma nova
tag, uma notificação é feita através de uma chamada a função
OnStartElementL, que, por sua vez, chama a função específica da tag
encontrada, que irá criar o elemento da estrutura NCM correspondente. O
primeiro problema encontrado foi o fato das chamadas feitas à função
OnStartElementL serem independentes, o que impossibilita saber qual tag foi
tratada antes ou qual será tratada depois. Para exemplificar o problema, a Figura
3 mostra um documento NCL simples.
Figura 3: Exemplo simples de uma aplicação NCL.
Neste documento, um elemento <media> encontra-se dentro de um
elemento <body>, que, por sua vez, está contido em um documento NCL. Na
estrutura NCM, isso é representado por um objeto chamado NclDocument, que
contém um Context, representando o nó body, e que, por sua vez, deve conter
o nó de media com id igual a video. O parser precisa, portanto, criar essa
estrutura e, para isso, precisa saber quem contém quem. Quando o parser SAX
Implementação 34
chama a função OnStartElementL para o nó media, não existe qualquer forma
de saber se esse nó faz parte do body ou de um outro nó de contexto. O parser
perde essa informação e, portanto, seria impossível criar a estrutura NCM
requerida. Esse problema não acontece no uso do parser DOM, uma vez que é
montada uma árvore representando todo o documento XML. Nesse caso, basta
fazer uma busca em profundidade nessa árvore para criar toda a estrutura do
modelo NCM.
No caso do parser SAX, a solução para o problema foi pensar no
procedimento de parser, que percorre o arquivo do início até o seu fim, como
uma busca em profundidade propriamente dita. A Figura 4, baseada na NCL da
Figura 3, ajuda a ilustrar esse pensamento onde a estrutura do documento NCL
é vista como uma árvore.
Figura 4: Documento NCL como uma árvore.
Para tratar a estrutura do documento NCL como uma árvore, duas
informações são importantes: o início e o fim de uma tag. Pode-se dizer como as
tags estão compostas (aninhadas) no documento NCL usando apenas essas
duas informações. Por exemplo, olhando a Figura 4, sabe-se que “regionBase” e
“descriptorBase” fazem parte do “head”, porque essa tag começa antes e
termina depois das outras duas. Em suma, toda tag pai da composição inicia
antes e termina depois das suas tags filhas. Assim, bastariam essas duas
Implementação 35
informações para que se fosse possível enxergar o documento como uma
árvore. As funções OnStartElementL e OnEndElementL do parser SAX em
questão podem ser usadas exatamente para alcançar esse objetivo, pois a
primeira informa o início, e a segunda, o fim de uma tag. Levando-se em conta o
que já foi dito, é possível perceber que o procedimento de parser, que lê o
arquivo NCL de cima para baixo, age, portanto, da mesma forma que uma busca
em profundidade.
Como já foi dito, para montar a estrutura NCM corretamente, é preciso
saber quem contém quem, e o primeiro passo para se descobrir isso é tratar o
parser SAX como uma busca em profundidade, como apresentado.
É possível usar uma estrutura de pilha para o armazenamento do
caminhamento feito por uma busca em profundidade. Esse procedimento, em si,
é bem conhecido e, se aplicado, quando a busca exemplificada alcançar o
elemento desejado, teremos na pilha dos elementos todos os seus ancestrais.
Essa é exatamente a informação necessária para a construção da estrutura
NCM. Basta, portanto, acessar a pilha para descobrir a qual nó o elemento
corrente pertence.
Quando uma tag é tratada, o objeto NCM correspondente deve ser inserido
na pilha. Quando a tag termina, culminando na chamada da função
OnEndElementL, o elemento do topo da pilha deve ser removido. É garantido
que o topo da pilha sempre corresponde ao elemento que está terminando, pois
toda tag que é aberta deve ser fechada, caso contrário, o documento NCL estará
inválido (mal formado). Ressalta-se que, para passar pelo procedimento de
parser aqui descrito, o documento NCL precisa ter sido validado antes.
Considerando a NCL presente na Figura 3 sem a tag “head” e suas filhas,
o procedimento parser descrito funcionaria da seguinte forma:
1- Início do Parser.
2- OnStartElementL da tag “ncl”. O elemento NCM NclDocument é
armazenado na pilha.
3- OnStartElementL da tag “body”. O elemento NCM Context é inserido
dentro do elemento que se encontra no topo da pilha, que, no caso, é o
elemento NclDocument. Depois disso, Context é inserido na pilha.
4- OnStartElementL da tag “port”. O elemento NCM Port é inserido
dentro do elemento que se encontra no topo da pilha, que, no caso, é o
elemento Context. Depois disso, Port é inserido na pilha.
5- OnEndElementL da tag “port”. O topo da pilha, que contém o elemento
Port, é removido.
Implementação 36
6- OnStartElementL da tag “media”. O elemento NCM ContentNode é
inserido dentro do elemento que se encontra no topo da pilha, que no
caso é o elemento Context. Depois disso, ContentNode é inserido na
pilha.
7- OnEndElementL da tag “media”. O topo da pilha, que contém o
elemento ContentNode, é removido.
8- OnEndElementL da tag “body”. O topo da pilha, que contém o elemento
Context, é removido.
9- OnEndElementL da tag “ncl”. O topo da pilha, que contém o elemento
NclDocument, é removido.
10- Fim do parser.
O procedimento descrito estaria correto se não fosse por um segundo
problema. A tag “media” precisa ser tratada antes da “port”, por ser referenciada
por ela. Existem, na NCL, algumas tags semelhantes a essa que dependem de
outras. Sendo a NCL uma linguagem declarativa baseada em XML, a ordem em
que as tags aparecem no documento, exceto a “head” e a “body”, não deve
influenciar no comportamento da aplicação resultante.
Para contornar esse problema duas soluções foram pensadas. A primeira
seria realizar mais de uma vez o parser no documento NCL. O número de vezes
seria determinado pelo nível de dependência das tags. Por exemplo, uma tag
“port” depende da “media”, porque faz referência a um elemento desse tipo.
Nesse caso, seriam necessárias duas passadas completas pelo documento
NCL, uma para identificar as tags “media” e outra para tratar a tag “port”. A fim
de evitar uso desnecessário de processamento, essa opção foi descartada. A
segunda solução seria armazenar, temporariamente, as tags dependentes
encontradas, que seriam tratadas depois, em um momento mais oportuno. Essa
opção foi implementada devido ao fato da estrutura de armazenamento ser
pequena e do seu descarte ser completamente efetuado após o tratamento das
tags dependentes.
Para entender o funcionamento da solução proposta, é preciso saber como
funcionam as relações de dependência entre tags NCL. As relações de
dependência são sempre entre duas irmãs de uma mesma relação de
composição, onde uma delas é sempre independente. Existe uma exceção
dessa regra para as tags “medias” que usam o parâmetro “refer”. Nesse caso, a
relação de dependência pode ocorrer entre tags de composições diferentes. A
implementação do Ginga-NCL para dispositivos fixos já possui um tratamento
Implementação 37
especial específico para esse caso que evita o acontecimento de erros e que foi,
portanto, mantido.
Uma outra exceção é a dependência que tags contidas no elemento
<body> possuem de outras pertencentes ao elemento <head>. Isso não gera
problemas, pois é garantido que todas as tags contidas no head serão tratadas
antes daquelas pertencentes ao body. Isso é verdade porque o nó head deve
obrigatoriamente ser sempre declarado antes do body, e o procedimento de
parser é sempre feito do início até o fim do documento ncl.
Para o caso geral de dependência, onde tags do nó body dependem de
outras tags do nó body ou onde tags do nó head dependem de outras do nó
head, é preciso esperar que o objeto ao qual a tag dependente faz referência
seja tratado para, somente então, lidar com ela. Considerando, portanto, o caso
geral, é garantido que, ao término do tratamento da tag pai de uma composição,
todas as suas tags filhas independentes tenham sido criadas. Restariam as suas
filhas dependentes, mas, como as suas irmãs já foram tratadas, é seguro, nesse
momento, cuidar delas. Sendo assim, tags dependentes são sempre tratadas no
momento em que a sua tag pai na relação de composição esteja terminando.
Para isso, é usada a estrutura de armazenamento representada na Figura 5.
Figura 5: Diagrama de Classes da estrutura usada para resolver o problema das
dependências entre tags.
A classe HandledTag armazena o objeto NCM referente à uma tag que já
tenha sido tratada na sua propriedade de nome NCLElement e é, então, inserida
Implementação 38
na pilha. Quando uma tag filha dependente é encontrada, uma instância da
classe DependentTag é criada para armazená-la. Esse objeto é, por sua vez,
inserido na lista de pendências da HandledTag que armazena o objeto NCM da
sua tag pai na composição. Uma DependentTag também possui uma lista de
pendências, pois, enquanto a tag dependente não tiver sido tratada, todas as
suas tags filhas também não poderão ser e, portanto, deverão ser colocadas na
sua lista de pendências como tags dependentes. Quando uma tag pai
independente termina, a sua lista de pendências é tratada. O mesmo é feito com
a lista de pendências de cada tag dependente que for tratada. Para exemplificar
o procedimento de parser, agora sem erros, considere novamente a NCL
presente na Figura 3. O parser, apenas para a tag “body”, funcionaria da
seguinte forma:
1- Início do Parser.
2- OnStartElementL da tag “ncl”. O elemento NCM NclDocument é
armazenado na pilha.
3- OnStartElementL da tag “body”. O elemento NCM Context é
inserido dentro do elemento que se encontra no topo da pilha,
que, no caso, é o elemento NclDocument. Depois disso, Context
é inserido na pilha.
4- OnStartElementL da tag “port”. O elemento NCM Port é uma
tag dependente e é inserido na lista de pendências do objeto
Context, que representa a tag “body”. Depois disso, Port é
inserido na pilha.
5- OnEndElementL da tag “port”. O topo da pilha, que contém o
elemento Port, é removido. Como esta é uma tag dependente, a
lista de pendências não é tratada agora.
6- OnStartElementL da tag “media”. O elemento NCM
ContentNode é inserido dentro do elemento que se encontra no
topo da pilha, que no caso é o elemento Context. Depois disso,
ContentNode é inserido na pilha.
7- OnEndElementL da tag “media”. O topo da pilha, que contém o
elemento ContentNode, é removido. Sua lista de pendências está
vazia, portanto nada é feito.
8- OnEndElementL da tag “body”. O topo da pilha, que contém o
elemento Context, é removido e a sua lista de pendências é
resolvida. O único elemento existente é o “port”, que pode ser
tratado agora, uma vez que “media” já foi resolvida. A lista de
Implementação 39
pendências do “port” também deve ser resolvida nesse momento,
mas, como ela está vazia, nada é feito.
9- OnEndElementL da tag “ncl”. O topo da pilha, que contém o
elemento NclDocument, é removido. Sua lista de pendências está
vazia, portanto nada é feito.
10- Fim do parser.
3.4. O Uso de Threads
“Uma thread pode ser definida como uma sub-rotina de um programa que
pode ser executada de forma assíncrona, ou seja, executada paralelamente ao
programa chamador”. (Berenger, Maia, 2002: 86) Em um ambiente multithread,
um processo associado a uma aplicação possui pelo menos uma thread,
chamada de thread principal. Uma aplicação pode ser totalmente executada na
thread principal, ou ter o seu processamento dividido em duas ou mais threads
diferentes. As diferentes threads de uma aplicação podem ser executadas
concorrentemente ou, no caso de existirem múltiplos processadores,
paralelamente.
“O conceito de concorrência é o princípio básico para o projeto e a
implementação dos sistemas multiprogramáveis” (Berenger, Maia, 2002: 40) ou
multitarefa, onde os programas compartilham os recursos computacionais
disponíveis. O Symbian é um sistema operacional multitarefa que implementa as
suas threads em modo kernel (Harrison, Richard et al, 2004). Além das
threads, o Symbian também oferece os Active Objects, que podem ser usados
com o mesmo objetivo das threads. A diferença entre os dois recursos é que os
Actives Objects são como threads implementadas em modo usuário e que não
sofrem qualquer tipo de preempção (Harrison, Richard et al, 2004).
A implementação do Ginga-NCL para terminais fixos faz muito uso de
threads por meio das API’s POSIX. Essas threads são usadas tanto para
permitir ações que executam em paralelo, importantes em aplicações que exijam
sincronismo, quanto para resolver outros problemas, como o do tratamento de
âncoras temporais, detalhado na Seção 3.6. As API’s de criação e manipulação
das threads no Symbian, entretanto, são diferentes daquelas oferecidas pelo
POSIX. Como visto na Seção 3.2, o uso de threads POSIX no Symbian só foi
possível graças ao P.I.P.S e ao Open C. Assim, o porte das classes que se
utilizam de threads POSIX pôde ser feito de forma direta, ou seja, nada da
Implementação 40
implementação de referência do Ginga-NCL para dispositivos fixos teve que ser
mudado.
O uso de threads, entretanto, consome muitos recursos, principalmente
os de memória, pois, para cada nova thread, uma nova pilha de execução é
criada. Por isso, em um ambiente de dispositivos com limitações de recursos, o
uso de threads normalmente não é recomendado. No sistema operacional
Symbian, em específico, a forma preferencial de se implementar uma aplicação
multitarefa, como o Ginga-NCL, não é com o uso das threads, mas sim com o
uso dos Actives Objects (Harrison, Richard et al, 2004: 41). Entretanto, a fim de
se facilitar o procedimento de porte, tentou-se manter o uso das threads. Assim
seria possível acelerar o processo de desenvolvimento e garantir a correção do
programa, uma vez que as características da implementação anterior do Ginga-
NCL, amplamente testado, seriam mantidas.
Um primeiro obstáculo encontrado para manter o uso das threads é o fato
de que muitos dos recursos oferecidos pelo Symbian só podem ser usados na
thread principal do processo de uma aplicação. Esse problema tem relação com
o modelo Client-Server Framework (Stichbury, 2004: 167) amplamente utilizado
no Symbian para a obtenção, manipulação e posterior liberação de recursos do
sistema. Muitos dos recursos só podem ser acessados através desse modelo,
onde um cliente solicita a um servidor um objeto que poderá ser usado na
manipulação de um recurso qualquer. Esse objeto só pode ser usado na thread
onde foi requisitado, e é somente através dele que o recurso associado pode ser
acessado. Vídeo, áudio e imagem são alguns exemplos de recursos geridos pelo
Client-Server Framework. Uma lista mais detalhada de recursos geridos por esse
modelo é encontrada em (Harrison, Richard et al, 2003: 501).
Ao iniciar uma aplicação Symbian, todo um ambiente de execução
predefinido é carregado (Harrison, Richard et al, 2004: 99). Esse ambiente inclui,
dentre outras coisas, controles para entrada de dados pelo usuário, gráficos e
acesso ao sistema de arquivos. Assim, recursos como os de acesso à tela do
dispositivo e exibição de gráficos em geral já são carregados por padrão na
thread principal do processo de qualquer aplicação Symbian (Harrison, Richard
et al, 2004). Como estes são recursos que são usados seguindo o modelo
Client-Server Framework, outras threads do processo não podem manipulá-los.
Assim, a instanciação e manipulação de objetos específicos de exibição do
Ginga-NCL, como o exibidor de vídeo, precisam ser feitas na thread principal
do processo de uma aplicação Symbian. Como a implementação de referência
do Ginga-NCL para dispositivos fixos lança diversas threads ao longo da sua
Implementação 41
execução, e muitas delas são responsáveis exatamente por instanciar e
manipular objetos de exibição, introduziu-se um problema que teve de ser
contornado.
Para solucionar o problema, e para manter o uso das threads, foi criado
um esquema de requisição entre as threads genéricas do processo e a thread
principal, onde as primeiras requisitariam instanciações ou ações pré-definidas
de objetos, e a segunda as atenderia. A idéia consiste em deixar a thread
principal em espera pelas requisições, enquanto as outras threads são
executadas e realizam essas requisições durante o seu processamento.
A implementação desse mecanismo faz uso de um vetor de requisições
compartilhado entre todas as threads. Uma ou mais threads podem, então,
armazenar uma ou mais requisições nesse vetor, sinalizando apropriadamente a
sua ação. Ao ter conhecimento dessa ação, a thread principal trata todas as
requisições pendentes na lista em questão. Ao final, a thread principal volta a
aguardar por novas requisições.
As threads podem fazer requisições a funções sem retorno, como a de
uma ação de “play” de vídeo, e depois continuar a sua execução normalmente.
Se for necessária uma requisição a funções com retorno de valor, como métodos
do tipo get, ou a instanciação de objetos, a thread deve, obrigatoriamente,
esperar pelo término da requisição, a fim de obter o retorno da função ou o
objeto instanciado. Nesses casos, a thread principal armazena, em uma
variável compartilhada, o retorno da função ou o objeto instanciado tão logo a
requisição for finalizada. Através dessa variável compartilhada, a thread
requisitante é capaz de recuperar a informação requerida.
A solução, embora tenha resolvido o problema, não foi suficiente para
manter o uso das threads na implementação do Ginga-NCL para dispositivos
portáteis. Na prática, a implementação das threads fazendo uso da solução
descrita mostrou-se extremamente lenta. Isso aconteceu a tal ponto de não ser
possível manter o sincronismo em aplicações muito simples, como, por exemplo,
a exibição de três imagens na tela. Infelizmente, a compatibilidade com a versão
anterior do Ginga-NCL no uso de threads não pôde ser mantida na
implementação proposta. Em seu lugar, os Active Objects foram usados,
conforme descrito na seção seguinte.
Implementação 42
3.5. Active Objects
Como foi abordado na seção anterior, o uso de threads não pode ser
mantido pela implementação proposta. Ao invés delas, optou-se por fazer uso
dos Actives Objects (Stichbury, 2004). Fazendo uma comparação entre os dois
recursos, é possível perceber a vantagem de se usar os Actives Objects. A
transferência do controle de um Active Object para outro, por exemplo, pode ser
até dez vezes mais rápida do que no caso de uma thread (Stichbury, 2004:
113). O consumo de memória é outra vantagem: enquanto uma thread pode
consumir, aproximadamente, 4Kb de memória de kernel e 8 Kb de pilha de
execução; um Active Object consome, em média, algumas centenas de Bytes ou
até menos (Stichbury, 2004: 113). A última vantagem que pode ser citada é que
não existe a preocupação com a proteção de dados compartilhados, uma vez
que os Active Objects se encontram em uma mesma thread (Harrison, Richard
et al, 2004). O único caso onde o uso dos Active Objects não é apropriado é
quando se deseja criar aplicações de tempo real que exigem tempos de resposta
muito pequenos. Nesses casos, o melhor é implementar a aplicação de tempo
real em uma thread de alta prioridade (Stichbury, 2004).
Em Symbian C++, entretanto, os Active Objects são usados normalmente
com o objetivo de controlar as chamadas às funções assíncronas e o seu
término. Portanto, para entender melhor o funcionamento dos Active Objects é
interessante entender, antes, o que são funções assíncronas. Uma função
assíncrona é aquela que retorna imediatamente após a sua chamada e executa
em paralelo ao procedimento que a chamou, normalmente em uma thread
separada. Esse procedimento chamador pode bloquear o seu processamento ou
continuar e realizar outras ações enquanto aguarda pelo fim da função
assíncrona. Quando a função assíncrona termina, um evento é lançado
indicando o seu sucesso ou erro. Esse evento deve ser capturado e tratado pelo
procedimento que chamou a função assíncrona.
Um Active Object é um objeto que estende a classe CActive (Symbian Ltd,
Nokia, 2006). As funções assíncronas controladas por um Active Object são nele
encapsuladas, e só devem ser chamadas através dele. Embora um Active Object
possa encapsular mais de uma função assíncrona, apenas uma pode ser
executada por vez. Ou seja, enquanto uma função assíncrona de um Active
Object estiver sendo processada, uma outra do mesmo objeto não pode ser
chamada. Se essa restrição for desrespeitada, existem três comportamentos
Implementação 43
possíveis: a aplicação é finalizada, a nova chamada não é realizada ou o
processamento da última função assíncrona é finalizado dando lugar à nova.
No Active Object também é implementado o método RunL, que é
responsável por tratar o término das suas funções assíncronas. Esse método
pode ser usado para analisar o resultado da chamada à função assíncrona,
realizar algumas finalizações ou até mesmo fazer outra chamada. Em suma,
pode-se fazer qualquer ação que se faça necessária.
Um Active Object é, portanto, de forma simplificada, um objeto que possui
um ou mais métodos que implementam ou realizam chamadas a quaisquer
funções assíncronas, e um outro método responsável por tratar das suas
finalizações. Uma API de vídeo, por exemplo, pode ser um Active Object, sendo
a sua função de Open assíncrona. Ao ser chamada pela aplicação, a função em
questão tem iniciada a sua execução em paralelo. A aplicação continua o seu
processamento e, em um determinado momento, a função Open termina a sua
execução. Então, o método RunL da API de vídeo em questão é chamado, e faz
as finalizações necessárias. Ele pode, por exemplo, emitir uma mensagem de
erro ao usuário caso o processamento da função Open tenha falhado.
Um outro objeto, o Active Scheduler, tem como responsabilidade chamar o
método RunL do Active Object quando uma das funções assíncronas desse
elemento tiver terminado. Quando isso acontece, diz-se que o Active Scheduler
fez o escalonamento de um Active Object. Existe apenas uma instância do
Active Scheduler por thread e o seu funcionamento é muito parecido com o de
um escalonador comum, tendo como diferença básica o fato dele não realizar
qualquer tipo de preempção.
Para fazer o procedimento descrito, o Active Scheduler define um
semáforo global à thread em que ele se encontra. Esse semáforo deve ser
sinalizado pelas funções assíncronas quando o processamento delas tiver
terminado. Dessa forma, o Active Scheduler sabe quando uma função
assíncrona terminou e que, portanto, um Active Object deve ser escalonado
através da chamada ao seu método RunL. A função assíncrona também precisa
alterar o valor de uma variável interna do seu Active Object associado,
denominada iStatus. Essa variável indica se o Active Object tem uma função
assíncrona finalizada ou ainda em execução. Essa ação é necessária porque é
possível existir mais de um Active Object gerido por um Active Scheduler, e a
simples sinalização do semáforo em si não indica qual Active Object teve a sua
função assíncrona finalizada. Ao alterar o valor da variável em questão,
Implementação 44
indicando que o Active Object possui uma função assíncrona já finalizada, o
Active Scheduler é capaz de descobrir qual Active Object pode ser escalonado.
O Active Scheduler fica, então, aguardando até que uma ou mais funções
assíncronas terminem e façam a sinalização. É importante ressaltar que,
existindo mais de um Active Object, mais de uma função assíncrona pode estar
sendo processada ao mesmo tempo. Em um cenário desses, duas ou mais
dessas funções podem ter terminado antes que o Active Scheduler tenha tido a
oportunidade de tratar a primeira delas. Por conta disso, quando o Active
Scheduler for tratar o término de uma função assíncrona, é normal que exista
mais de um Active Object elegível a ter a sua função RunL executada. É
interessante, portanto, que o Active Scheduler faça o escalonamento daquele
Active Object que for mais crítico para o sistema, ou seja, aquele que for mais
prioritário. Dessa forma, todo Active Object precisa determinar, no momento da
sua construção, uma prioridade para si mesmo de tal forma que o Active
Scheduler possa usar essa informação no momento em que estiver fazendo o
escalonamento. Um outro ponto importante é que os Active Objects devem ser
registrados junto ao Active Scheduler para que possam ser escalonados.
Normalmente, um Active Object faz esse registro logo na sua construção, mas
isso pode ser feito em qualquer momento, desde que antes da chamada a uma
função assíncrona. O Active Scheduler, por sua vez, mantém uma lista de Active
Objects registrados com base nas suas prioridades, e faz o escalonamento com
base nessa lista.
Uma vez tendo recebido a sinalização do término de uma função
assíncrona, o Active Scheduler escalona o Active Object mais prioritário que
possui uma função desse tipo finalizada e faz a chamada ao seu método RunL.
Esse método será executado sem interrupções, até o seu fim, uma vez que não
existe preempção no uso dos Actives Objects. Quando o método RunL termina, o
Active Scheduler volta a aguardar por novas sinalizações. O funcionamento do
Active Scheduler pode ser, portanto, resumido em um loop pelo qual ele:
1- Aguarda por uma sinalização de uma função assíncrona que tenha
terminado;
2- Recebe a sinalização e busca pelo Active Object de maior
prioridade que possui uma função assíncrona finalizada, o que é
possível de se descobrir ao se consultar o valor da variável
iStatus dos Actives Objects;
3- Ao final da busca, chama o método RunL do objeto escalonado;
Implementação 45
4- Quando o método RunL terminar, volta a aguardar por uma nova
sinalização.
A qualquer momento nesse loop, novos Active Objects podem se registrar
junto ao Active Scheduler. Informações mais detalhadas sobre os Active Objects
podem ser encontradas em (Stichbury, 2004: 127).
Na implementação apresentada, entretanto, o mais interessante é saber
como fazer uso do Active Object com o objetivo de suprimir o uso das threads
POSIX tão utilizadas na implementação de referência do middleware Ginga-NCL
para dispositivos fixos. Para tanto, é recomendado fazer uso dos Background
Active Objects (Symbian Ltd, Nokia, 2006), que são Active Objects de baixa
prioridade.
A idéia é encarar o Background Active Object como uma thread em si. No
seu método RunL deve ser implementado o procedimento que seria
implementado na função run da thread POSIX. Como não existe preempção no
uso dos Active Objects, o método RunL não pode gastar muito tempo durante o
seu processamento, pois isso impediria que outros Active Objects, alguns talvez
mais prioritários, fossem escalonados por um longo período de tempo. O
procedimento deve, então, ser implementado no método RunL do Background
Active Object de modo que não consuma muito tempo de processamento. Se o
procedimento for muito pesado, ele deve ser dividido em N partes diferentes.
Cada uma dessas N partes deve ser leve o suficiente para não consumir muito
tempo de processamento do método RunL. A idéia é que a execução dessas N
partes seja feita de forma intercalada, com o objetivo de dar ao Active Scheduler
a oportunidade de escalonar um outro Active Object de maior prioridade. Por
isso que é importante que o Background Active Object possua uma prioridade
baixa, assim, entre a execução de uma das N partes do procedimento e outra, é
garantido que outros Actives Objects mais prioritários serão escalonados. Caso o
procedimento seja leve o suficiente para ser executado todo de uma vez, esses
cuidados não precisam ser tomados.
Como já mencionado, um Active Object só fica elegível pelo Active
Scheduler quando o semáforo desse elemento é sinalizado por uma função
assíncrona e quando o valor da sua variável iStatus é modificado de forma
apropriada. Dessa forma, para iniciar a execução do procedimento
implementado no método RunL de um Background Active Object, um outro
método, que aqui será chamado de start, deve ser implementado em
substituição a função assíncrona. A chamada ao método start deve fazer com
que o Background Active Object em questão fique elegível pelo Active
Implementação 46
Scheduler. Para isso, o método em questão precisa apenas sinalizar o semáforo
controlado pelo Active Scheduler e atualizar a variável iStatus como já descrito
nesta seção. Ao chamar esse método, o Background Active Object fica elegível
pelo Active Scheduler e o seu método RunL será chamado assim que nenhum
Active Object mais prioritário estiver na fila.
Quando o método RunL é chamado, o procedimento implementado nele
começa a ser executado. Se houve a necessidade de dividi-lo em N partes, uma
dessas partes é executada e, então, o método start deve ser novamente
chamado, fazendo o Background Active Object ficar mais uma vez elegível pelo
Active Scheduler. Isso permite que o método RunL seja chamado novamente
para que uma outra das N partes do procedimento em questão seja executada.
Esse procedimento todo se repete até que todo o método RunL tenha sido
executado e o procedimento implementado nele tenha, conseqüentemente,
terminado. Se não houve a necessidade de dividir o procedimento em mais de
uma parte, então ele é completamente executado logo na primeira chamada ao
método RunL.
O único problema da técnica apresentada é modelar, quando necessário, o
procedimento a ser implementado no método RunL adequadamente de tal forma
que se possa dividi-lo em N partes.
Na implementação Ginga-NCL para dispositivos fixos, o uso de threads
POSIX possui uma abstração que é representada por uma classe chamada
Thread. Essa classe é usada pela máquina de apresentação quando é
necessário executar ações concorrentemente. Um exemplo é quando se deseja
implementar um conector onde estejam definidas ações que devem ser
executadas em paralelo (ABNT/CEET-00:001.85, 2007: 54). Nesse caso, a
máquina de execução cria e lança, para cada ação, um objeto da classe Thread.
Assim, a máquina de apresentação não precisa se preocupar em como essa
classe é implementada, sendo sua única exigência que a classe Thread ofereça
pelo menos algum nível de concorrência.
O único ponto da implementação original que teve que ser modificado com
o objetivo de se remover o uso das threads POSIX foi, portanto, a
implementação da classe Thread. No Ginga-NCL para dispositivos portáteis, a
classe abstrata Thread é, na verdade, um Background Active Object. Essa
substituição foi o suficiente para fazer com que as aplicações fossem executadas
com maior velocidade. O sincronismo se tornou, então, possível, e aplicações
até dez vezes maiores puderam ser desenvolvidas. Ressalta-se que, embora o
Background Active Object tenha sido utilizado, em nenhum caso houve a
Implementação 47
necessidade de se dividir o procedimento implementado no método RunL em
mais de uma parte. Ou seja, todos os procedimentos eram leves o suficiente
para serem executados de uma só vez.
Existe, porém, o caso do tratamento de âncoras temporais, que também
faz uso da classe Thread, onde a substituição da implementação das threads
POSIX pelo Background Active Object introduziu, nesse caso específico, um
erro. Esse problema é apresentado juntamente com a sua solução na próxima
seção.
3.6. O Tratamento de Âncoras Temporais
A substituição das threads POSIX pelos Active Objects introduziu um erro
no tratamento das âncoras temporais.
Para entender como esse erro foi gerado e a sua solução, é necessário,
antes, introduzir o conceito de âncoras temporais. Também é importante
apresentar como foi feita a sua implementação na versão do Ginga-NCL para
dispositivos fixos.
Uma âncora temporal define um intervalo de tempo dentro da duração da
apresentação de um elemento de mídia qualquer. Para criar uma âncora
temporal, usa-se o elemento <area> — como em toda a criação de ancoras — e
especifica-se os seus atributos “begin” e “end”. Esses atributos representam,
respectivamente, o início e o fim do intervalo relativos ao início da apresentação
do conteúdo de mídia. Essa tag deve ser definida como um elemento do nó de
mídia em que se quer definir um intervalo temporal. Como exemplo, a Figura 6
ilustra um cenário onde várias âncoras temporais são definidas.
Implementação 48
Figura 6: Exemplo de um documento NCL com âncoras temporais.
Um elemento <area> definido em um nó de mídia (<media>) pode ser
referenciado como uma interface do objeto de mídia, como exemplifica o link
lnk1 da Figura 6. Âncoras temporais podem, assim, serem usadas com o
objetivo de se fazer sincronismo temporal entre trechos de mídias. Na Figura 6,
quando o vídeo definido tiver completado 5 segundos, uma transição de estado
de evento de ”start”, associado à sua primeira âncora, ocorre, indicando o início
do intervalo. Analogamente, quando o vídeo alcançar os dez segundos, uma
transição de estado de evento de ”stop”, associada a mesma âncora, ocorre,
indicando o fim do intervalo. A máquina de apresentação capta essas transições
de estados de eventos e, se houver uma ação associada a uma dessas
transições, essa ação é executada. Como exemplo, no link lnk1 da Figura 6, é
Implementação 49
especificado que a apresentação da imagem1 deve ser iniciada quando a
primeira âncora definida para o vídeo começar sua exibição. A máquina de
apresentação capta a transição de estado de evento de início da âncora e inicia
a apresentação da imagem1, conforme especificado.
Para implementar uma âncora temporal, precisa-se, basicamente,
contabilizar o tempo decorrido da exibição da mídia, lançando as transições de
estados de eventos “start” e “stop” nos momentos definidos pelas suas âncoras.
Na implementação de referência do Ginga-NCL para dispositivos fixos, a
máquina de apresentação dispara, para cada mídia possuidora de âncoras
temporais, uma thread separada. Essa thread fica responsável por organizar
uma fila crescente com os tempos definidos pelos elementos <area> associados.
Essa fila é usada para descobrir os momentos em que as transições de estados
de eventos devem ser disparadas. A Figura 7 ilustra como fica,
simplificadamente, a fila do exemplo apresentado na Figura 6:
Figura 7: Exemplo de fila de tempos definidos em âncoras temporais.
De posse dessa lista, resta à thread contabilizar o tempo da mídia e
lançar as transições de estados de eventos nos tempos definidos pela fila. A
contagem do tempo decorrido das mídias é sempre feita nos próprios objetos de
exibição. No caso de mídias com tempo de duração pré-estabelecido, como as
de vídeo ou de áudio, suas API’s de exibição normalmente possuem uma função
que retorna o tempo decorrido de apresentação. Quando as mídias não
possuem tempo de duração definido, ou quando as suas API de exibição não
fornecem uma função que retorne o tempo decorrido de apresentação, a
implementação dos seus exibidores deve, obrigatoriamente, criar um contador
próprio. Com a fila criada e com a informação do tempo decorrido de
apresentação da mídia, a thread realiza o seguinte procedimento de quatro
passos:
1- Remove o primeiro elemento da fila;
2- Calcula a diferença entre o tempo do elemento removido da fila e o
tempo corrente da mídia. Essa diferença é exatamente o tempo que
será necessário aguardar até que o tempo definido por uma das
âncoras seja alcançado;
3- Usa diferença encontrada em um comando de sleep.
Implementação 50
4- Acorda do comando de sleep. Nesse momento, o tempo definido
por uma das âncoras foi alcançado. A implementação lança,
portanto, uma transição de estado de evento de start ou stop
dependendo se o tempo alcançado foi de início ou término de uma
âncora;
Esse procedimento se repete até que a fila tenha se esvaziado. Isso basta
para que o uso de âncoras temporais seja tratado corretamente. Na
implementação apresentada nesta dissertação, no entanto, o uso das threads,
como já foi apresentado em seções anteriores, é proibitivo. No lugar delas, foi
feito o uso dos Active Objects, que executam todos na thread principal do
processo associado a aplicação Ginga-NCL.
Pelo fato dos Actives Objects se encontrarem em uma mesma thread, a
chamada a uma função de sleep dentro das funções RunL dos Actives Objects
colocaria todo o processo da aplicação Ginga-NCL em espera, impedindo que
outras ações pudessem ser feitas. O tratamento das âncoras temporais tem,
então, de ser feito sem a necessidade de bloquear o Active Object e,
conseqüentemente, a aplicação como um todo.
A solução para esse problema foi usar um Active Object especial, o
CTimer (Symbian Ltd, Nokia, 2006), e implementá-lo como um Background
Active Object. CTimer é como um Active Object normal, a não ser pelo fato dele
já possuir métodos que encapsulam funções assíncronas de contagem de
tempo. O mais importante deles é o After, que recebe como parâmetro um
tempo a ser aguardado. Quando chamado, esse método chama uma função
assíncrona de sistema passando no seu parâmetro o tempo a ser aguardado.
Essa função, por sua vez, executa em paralelo ao Active Object e aguarda pela
passagem do tempo especificado no seu parâmetro. Quando o tempo termina, a
função notifica o fato, sinalizando o semáforo do Active Scheduler. Isso faz com
que, em algum determinado momento, o método RunL do Active Object em
questão seja chamado pelo Active Scheduler.
A solução encontrada para o tratamento das âncoras temporais foi,
portanto, realizar a sua implementação no método RunL de um CTimer. Para
fazer essa implementação, foi preciso analisar o procedimento de quatro passos
necessário para o tratamento de âncoras temporais. Se observado com cuidado,
esse procedimento pode ser dividido em duas partes: A primeira (1) compreende
os passos 1, 2 e 3 do procedimento, sendo que, no passo 3, o método After do
CAtive deve ser usado ao invés do sleep. A segunda parte (2) compreende o
Implementação 51
passo 4, que ocorre logo depois que o tempo de espera tiver terminado. Essas
duas partes foram implementadas separadamente no método RunL do CTimer,
que controla o procedimento de âncoras temporais.
Para iniciar a execução do método RunL, um outro método teve que ser
implementado com o objetivo de fazer com que o CTimer ficasse elegível pelo
Active Scheduler, como descrito na Seção 3.5. Ao fazer a chamada desse
método, o CTimer fica elegível pelo Active Scheduler e, em algum determinado
momento, o método RunL do CTimer é chamado. Quando a função RunL é
finalmente chamada, somente (1) é executado. Assim que o tempo de espera
termina, RunL é novamente escalonado e, dessa vez, (2) é executado com o
objetivo de lançar o evento de “start” ou de “stop” da ancora temporal. Se
existirem mais elementos na fila de tempos definidos pelas ancoras temporais de
uma mídia, (1) é chamado novamente, e o ciclo é reiniciado.
Implementado dessa forma, o tratamento de âncoras temporais na
implementação do Ginga-NCL para dispositivos portáteis foi minimamente
alterado, mantendo as características base da implementação para dispositivos
fixos, com a vantagem que o uso de threads foi completamente removido,
contribuindo para o funcionamento adequado e otimizado da nova
implementação.
3.7. Exibidores no Symbian C++
Os exibidores são os elementos responsáveis pela apresentação do
conteúdo dos objetos de mídia. Os exibidores dependem da plataforma de
desenvolvimento e, portanto, representam a parcela com mais problemas de
portabilidade do middleware Ginga-NCL.
Para facilitar o procedimento de porte do Ginga-NCL, uma camada de
abstração de exibidores foi desenvolvida desde sua implementação de
referência para dispositivos fixos. Essa camada implementa uma série de
funções que devem ser mapeadas nas API’s específicas dos exibidores da
plataforma implementada. A máquina de apresentação precisa acessar apenas
essa camada a fim de controlar a execução de um exibidor, não tendo a
necessidade de se preocupar com as características específicas da plataforma
de desenvolvimento.
Implementação 52
No controle da execução dos exibidores, a máquina de apresentação
precisa associar os objetos de exibição às regiões especificadas pelo documento
NCL. Esse procedimento, em si, exige o acesso ao display do dispositivo, o que
também é um procedimento específico de plataforma. Pelo mesmos motivos do
caso dos exibidores, uma camada de abstração para o acesso ao display do
dispositivo foi definida. De forma similar, suas funções devem ser mapeadas em
API’s específicas da plataforma. A máquina de apresentação usa essa camada
para gerenciar as regiões da aplicação NCL e, assim como no caso dos
exibidores, não precisa se preocupar com as características específicas da
plataforma de desenvolvimento.
Em uma apresentação de uma aplicação NCL, a máquina de apresentação
cria, primeiro, as regiões definidas no documento NCL. Depois, ao longo da
apresentação da aplicação, solicita ao Gerenciador de Exibidores, visto na
Seção 3.1, a instanciação dos elementos de mídia e os associa às regiões
previamente criadas.
A máquina de apresentação também pode acessar os exibidores através
da sua camada de abstração. Isso é necessário para, por exemplo, iniciar,
pausar ou parar um vídeo, aumentar ou diminuir o som de um áudio, dentre
outras ações desse tipo. A Figura 8 ilustra o procedimento que acaba de ser
descrito, levando em conta as camadas de abstração mencionadas.
Implementação 53
Figura 8: Acesso das camadas de abstração dos exibidores e do Display do dispositivo
por parte da máquina de apresentação.
O procedimento, como um todo, é independente de plataforma, e não
necessitou sofrer alterações. O que precisou ser feito na implementação corrente
foi o mapeamento das camadas de abstração de display e de exibidores para as
API’s específicas do Symbian.
Em Symbian, o acesso ao display é feito através de objetos chamados de
Window. Entretanto, a apresentação de mídias na tela normalmente não é feita
através desse recurso. Ao invés dele, usam-se os Controls, já que o uso direto
de uma Window consome muitos recursos e é muito complexo. Os Controls, por
sua vez, abstraem o uso das API’s providas pela Window e compartilham esse
recurso entre si, ou seja, dois ou mais Controls podem fazer uso de uma mesma
Window. Normalmente, uma aplicação Symbian possui apenas uma Window
associada, pois a criação de mais objetos desse tipo causaria uma degradação
do sistema. Os Controls, portanto, são usados para implementar as diferentes
interfaces de uma aplicação e normalmente compartilham uma única Window.
Por exemplo, um Control poderia ser responsável por mostrar uma lista de
opções na tela e, um outro, por apresentar uma imagem de fundo. Ambos
podem compartilhar a mesma Window, economizando, assim, recursos.
Implementação 54
Para implementar um Control, é preciso estender a classe CCoeControl
(Symbian Ltd, Nokia, 2006) implementando alguns dos seus métodos abstratos.
O mais importante deles é o Draw, que é usado para aplicar alterações na tela
do dispositivo. Quando um Control é iniciado ou quando o seu método DrawNow
é utilizado, a função Draw é chamada. Dentro da função Draw, o objeto
CWindowGc (Symbian Ltd, Nokia, 2006), que pode ser obtido através da chamada
a função SystemGc pertencente ao Control, deve ser usado para fazer o desenho
na tela. Nesse objeto estão encapsuladas todas as funções de desenho, como
definição de cor, estilo do pincel, criação de formas geométricas, dentre outras.
A apresentação de objetos no display de qualquer dispositivo com o Symbian OS
instalado é feita, portanto, na função Draw dos Controls da aplicação por meio do
objeto CWindowGc. Quando a máquina de apresentação associa, na
implementação proposta, um exibidor a uma região NCL, estará, na verdade,
associando-o a um Control criado para aquela região.
Uma limitação que pode ser citada na forma como é feito o gerenciamento
gráfico no Symbian, é a existência de apenas uma camada gráfica de
apresentação. Isso significa que imagens e vídeos, ou quaisquer outros objetos
de exibição, serão sempre apresentados em uma mesma camada. Uma
diferença da implementação aqui exposta em comparação à implementação de
referência para dispositivos fixos é que, para dispositivos portáteis, nenhum
objeto pode ser apresentado por cima de um vídeo. Essa limitação ocorre
justamente por causa da limitação da existência de uma única camada.
Entre os vários exibidores de tipos de mídias diferentes, já foram
implementados os de imagem estática, áudio, vídeo e HTML.
Para apresentar uma imagem na tela do dispositivo, é preciso usar, dentro
do método Draw de um Control, o método DrawBitmap pertencente à classe
CWindowGc. Esse método recebe como parâmetro a posição onde a imagem
deve ser desenhada, além de um objeto do tipo CFbsBitmap, que é usado para
carregar, através do seu método Load, imagens estáticas armazenadas dentro
de um buffer ou de algum arquivo em disco. O CFbsBitmap, entretanto, só é
capaz de carregar imagens do tipo mbm (Multi-BitMaps), que é um tipo
específico de imagem usada na plataforma Symbian.
O vídeo e o áudio são providos com o uso da Multi Media Framework
(MMF), onde são definidas as classes CVideoPlayerUtility e
CMdaAudioPlayerUtility, usadas, respectivamente, para tocar vídeos e
áudios. O funcionamento dessas duas classes é muito similar. Ambas oferecem
funções idênticas capazes de carregar um vídeo ou um áudio de origens
Implementação 55
diferentes. Um exemplo é a função OpenFileL, que abre um vídeo ou áudio de
uma arquivo salvo em disco. Caso a abertura do arquivo seja bem sucedida, o
método Play das classes CVideoPlayerUtility e CMdaAudioPlayerUtility
pode ser usado para começar a tocar o objeto de mídia. Existem outras funções
nessas classes que podem ser usadas na manipulação das propriedades do
vídeo ou do áudio. O vídeo, especificamente, pode ter as suas dimensões
modificadas pelo seu Control associado, ou seja, o Control pode fazer, quando
necessário, uso das funções de redimensionamento providas pelo
CVideoPlayerUtility. O áudio, por outro lado, não possui características de
visualização e, portanto, não precisaria ter um Control associado, mas essa
associação foi feita mesmo assim com o objetivo de manter a padronização na
implementação.
Os dispositivos Symbian possuem uma lista de tipos de áudio e vídeo que
possuem plug-ins associados. As classes CVideoPlayerUtility e
CMdaAudioPlayerUtility, quando tentam carregar um objeto de áudio ou de
vídeo, acessam essa lista para descobrir se o dispositivo possui o plug-in
adequado para tocar o elemento que está sendo carregado. Se o dispositivo
possuir o plug-in apropriado, quando o comando Play for executado, as classes
CVideoPlayerUtility e CMdaAudioPlayerUtility associarão o objeto de
mídia carregado a esse plug-in, e começarão a tocá-lo. Dessa forma, essas
classes abstraem os tipos de áudio e vídeo que podem ser tocados, ou seja, elas
podem ser usadas para tocar qualquer tipo de mídia de áudio ou vídeo, bastando
apenas que o dispositivo possua os plug-ins necessários.
Finalmente, o exibidor HTML também foi implementado. Não existe API
genérica para a apresentação de documentos HTML no Symbian, portanto foi
necessário fazer uso de uma API específica da plataforma S60. Isso significa
que o exibidor HTML funcionará apenas em dispositivos específicos dessa
plataforma. A classe usada foi a CBrCtlInterface, sendo o mais importante
dos seus métodos o LoadUrlL, que carrega uma página HTML de uma URL
qualquer. Para criar um objeto da classe CBrCtlInterface é necessário usar a
função estática CreateBrowserControlL, passando o Control associado a esse
exibidor em um dos seus parâmetros. Qualquer alteração nesse Control vai, a
partir de então, refletir no exibidor HTML.
A existência das camadas de abstração descritas facilitou muito o
procedimento de porte dos exibidores, que se tornou algo bem simples e direto.
O maior problema encontrado na implementação dos exibidores foi que, apesar
de existir documentação para as API’s específicas Symbian, a informação
Implementação 56
provida normalmente é muito sucinta e, em alguns casos, insuficiente. Os
exemplos encontrados também são muito complexos e acabavam dificultando
ainda mais o procedimento de aprendizagem.
3.8. Considerações Finais
Durante a implementação do Ginga-NCL para dispositivos portáteis, ficou
clara a importância que um sistema aberto e padronizado tem no processo de
desenvolvimento.
A plataforma nativa do Symbian, e seu ambiente de desenvolvimento
Symbian C++, foi projetada especificamente para os dispositivos portáteis e é
muito particular. As API’s de desenvolvimento Symbian C++, por exemplo,
guardam poucas semelhanças com as API’s padrões de desenvolvimento C++,
linguagem da qual Symbian C++ se baseia. Isso dificulta qualquer procedimento
de porte e força os programadores a aprenderem um novo conjunto de API’s de
desenvolvimento bem diferente daqueles que estão acostumados. Dessa forma,
o procedimento de desenvolvimento torna-se muito complexo e pouco atrativo
para a plataforma em questão. O fato da plataforma Symbian ser aberta contribui
para a observância desses problemas de padronização e especificidade da
plataforma Symbian, e, principalmente, para sua melhora.
Com o apoio da comunidade, a Symbian Ltd, criadora do sistema
operacional Symbian, foi capaz de perceber a importância da padronização de
uma plataforma e ofereceu o P.I.P.S.. Mais tarde, a Nokia, que desenvolve a API
específica S60, disponibilizou o Open C, o que contribuiu ainda mais para a
padronização e, conseqüentemente, para o porte de aplicações desenvolvidas
em outras plataformas. A falta da biblioteca STL, usada comumente em
programas desenvolvidos em C++, também prejudicava o procedimento de
porte. Mais uma vez, por ser uma plataforma aberta, um integrante da
comunidade Symbian pôde fazer, com a ajuda da já disponibilizada P.I.P.S., o
seu próprio porte de uma implementação STL para o Symbian OS.
Os esforços em torno da disponibilização das bibliotecas P.I.P.S, Open C e
STL contribuem muito para o desenvolvimento e o porte de aplicações para a
plataforma Symbian, e, conseqüentemente, contribuíram muito para o porte e o
desenvolvimento do Ginga-NCL para dispositivos portáteis. No início da
implementação, essas bibliotecas não foram utilizadas, como é descrito na
Seção 3.2. A opção foi implementar mapeamentos das API’s utilizadas na
Implementação 57
implementação de referência para dispositivos fixos em API’s específicas da
plataforma Symbian, o que se demonstrou ser muito complexo e demorado.
Quando as bibliotecas P.I.P.S., Open C e STL passaram a ser utilizadas, o
desenvolvimento tornou-se mais simplificado. Sem essas bibliotecas, o
desenvolvimento completo do Ginga-NCL para dispositivos portáteis seria, sem
dúvida, muito mais complicado além do que demoraria muito mais tempo.
Em outros sistemas abertos, como o Linux, espera-se ter uma facilidade de
porte e de desenvolvimento igual ou talvez até mesmo maior do que no
Symbian. Por outro lado, sistemas de plataforma fechada, como o BlackBerry,
possuem sua própria plataforma de desenvolvimento e provavelmente não
devem oferecer suporte à maioria das bibliotecas padrão. Isso certamente
dificultaria muito o porte e desenvolvimento do Ginga-NCL, como de qualquer
outra aplicação.
Outra questão que deve ser mencionada é a alteração do módulo
Conversor na implementação do Ginga-NCL para dispositivos portáteis. Essa
tarefa consumiu muito tempo, uma vez que praticamente todo o módulo em
questão teve que ser re-implementado, mantendo-se inalteradas somente as
suas interfaces com o resto da arquitetura Ginga-NCL. A experiência obtida com
a implementação do módulo Conversor evidenciou que não seria necessário
fazer uso dos recursos oferecidos pelo modelo DOM. Normalmente, o parser
DOM é usado quando a estrutura do documento XML é muito complexa, com
muitos níveis e muitas referências entre objetos de níveis diferentes, quando é
necessário fazer uso pontual da estrutura XML em diversos momentos da
execução do programa, quando é preciso acessar elementos diferentes da
estrutura XML em um mesmo momento, ou quando é necessário alterar o
documento XML.
Foi possível avaliar, entretanto, que a NCL em si não é suficientemente
complexa a ponto de exigir o uso do DOM na implementação do módulo
Conversor, que foi re-projetado utilizando a API SAX na versão para dispositivos
portáteis. Documentos NCL normalmente não possuem tantos níveis e as
referências entre elementos podem ser resolvidas sem muitas dificuldades.
Portanto, nenhuma característica dessa linguagem impede, aparentemente, o
uso do SAX, ou exige que o DOM seja usado. Outro ponto que deve ser
observado é que também não há a necessidade de fazer acessos repetidos à
estrutura do documento NCL. No Ginga NCL, o documento NCL recebido da
emissora ou de qualquer outra fonte deve ser convertido em uma estrutura de
dados baseada no modelo NCM. A partir de então, somente essa estrutura é
Implementação 58
usada, sendo desnecessário acessar novamente o documento NCL e,
conseqüentemente, manter a estrutura montada por um parser DOM.
Existe, entretanto, um recurso do Ginga-NCL que lida com elementos da
linguagem NCL e que não foi implementado na versão desse middleware para
dispositivos portáteis. Esse recurso é o tratamento de edição ao vivo de
aplicações NCL. O Ginga-NCL permite que sejam feitas edições ao vivo em
qualquer aplicação NCL que esteja sendo apresentada. Para fazer uma edição,
um documento NCL específico deve ser entregue ao Ginga-NCL, que, por sua
vez, o processa e aplica as alterações na estrutura NCM da aplicação que está
sendo apresentada. Dessa forma, igualmente para o caso das edições, o uso do
DOM parser também não se faz necessário. Sem a necessidade de uso do
parser DOM, ficou evidenciado que o SAX demonstra-se muito mais vantajoso
pela sua eficiência e pelo seu baixo consumo de memória, não só em
dispositivos portáteis, mas também em terminais fixos.
Uma outra questão interessante que deve ser salientada diz respeito ao
uso das threads na implementação para dispositivos portáteis, o que
demonstrou claramente o problema das limitações de recursos encontradas
nesses dispositivos. Como foi apresentado nesta dissertação, o uso de threads
POSIX na implementação do Ginga-NCL para dispositivos portáteis tornou-se
proibitivo, fazendo com que a execução das aplicações NCL ficasse
extremamente lenta. Para contornar o problema, as threads foram substituídas
pelos Active Objects, permitindo a execução das aplicações de forma correta e
eficiente, mesmo sem o paralelismo das threads. Em outras plataformas, a
possibilidade do uso das threads vai depender de como esse recurso é
implementado e de como é o seu consumo de recursos. Todavia, se o uso de
threads em qualquer outra plataforma também for proibitivo, é possível definir
outras formas de escalonamento que viabilizem a execução do Ginga-NCL,
como já foi demonstrado com o uso dos Active Objects no Symbian.
A implementação dos exibidores, por sua vez, é muito dependente de
plataforma. O fato do Ginga-NCL possuir uma abstração do uso desses
elementos facilitou muito a implementação, algo que certamente deve se repetir
na implementação do Ginga-NCL em outras plataformas. Em Symbian, os
exibidores de vídeo e de HTML foram os mais complicados de se implementar.
O exibidor de texto certamente é o mais problemático de todos, tanto que não foi
possível, ainda, implementá-lo na versão atual do Ginga-NCL para dispositivos
portáteis. Por conta disso, a sua implementação é citada nos trabalhos futuros
Implementação 59
desta dissertação. A implementação dos exibidores em outras plataformas
depende muito de como são as suas API’s específicas de exibição.
A implementação do Ginga-NCL para dispositivos portáteis resultante do
trabalho apresentado nesta dissertação foi testada em um emulador de
dispositivo Symbian S60 e em dois dispositivos portáteis. Os testes são
detalhados no Capítulo 4.
Em relação à implementação do Ginga-NCL para dispositivos fixos,
algumas limitações devem ser observadas. A primeira delas é que não é
possível apresentar uma imagem sobre um vídeo por causa da existência de
uma única camada gráfica de apresentação, como é descrito na Seção 3.7. A
segunda limitação que pode ser citada, é a impossibilidade de se definir níveis
de transparência para os vídeos. Como última limitação, pode-se citar que a
soma total dos tamanhos das mídias apresentadas ao mesmo tempo em uma
aplicação NCL não pode ser muito alta. O limite para isso depende muito do
dispositivo em que a aplicação NCL está executando, mas, nos testes
realizados, somas maiores que 2Mb causaram o término da aplicação por falta
de recursos.
Como é descrito no Capítulo 4, o funcionamento do Ginga-NCL foi testado
em diferentes aplicações NCL, sendo que o funcionamento delas ocorreu de
forma idêntica no emulador e nos dispositivos portáteis, e não foi observada
qualquer degradação do sistema. As aplicações NCL executaram sem aparente
perda de eficiência e o sincronismo funcionou adequadamente. Dessa forma,
pode-se concluir que a implementação apresentada nessa dissertação foi bem
sucedida.
As ferramentas necessárias para a compilação do Ginga-NCL, o emulador
e os dispositivos usados, bem como o procedimento de instalação do Ginga-
NCL, são apresentados no Apêndice A desta dissertação.
4 Testes Sistêmicos
O objetivo deste capítulo é apresentar os testes realizados para ajudar a
identificar erros na implementação do Ginga-NCL em dispositivos portáteis.
Foram realizados apenas testes sistêmicos, onde várias funcionalidades são
testadas em conjunto. O objetivo foi verificar o comportamento da execução
levando-se em conta a conjunção das funcionalidades, ao invés de se avaliar
apenas o funcionamento pontual de cada uma delas, como é feito nos testes
unitários. A melhor forma de se fazer esse tipo de teste é desenvolver uma
aplicação NCL propriamente dita, onde vários recursos são exercitados ao
mesmo tempo. Por exemplo, uma simples aplicação NCL pode por a teste a
execução do parser e a criação de regiões, descritores, mídias e portas.
Os testes realizados, portanto, consistem na execução de aplicações NCL
que, ao final, também servem como prova de conceito da implementação. Para
cada uma das aplicações, serão apresentados a sua dinâmica, os exibidores
usados e os problemas mais relevantes identificados, juntamente com as suas
respectivas soluções. Também serão apresentadas telas ilustrativas de cada
uma dessas aplicações quando executadas em um emulador de dispositivo
Symbian S60. Além do emulador, os testes também foram executados em dois
dispositivos reais, como descrito no Anexo A.
4.1. Formula 1
A primeira aplicação desenvolvida para a implementação do Ginga-NCL
para dispositivos portáteis foi uma sobre corrida de Fórmula 1. Nela, um vídeo de
fórmula 1 é exibido em um pouco mais da metade da tela do dispositivo. O resto
do espaço é usado para apresentar três opções de interação. A Figura 9 mostra
esse cenário.
Testes Sistêmicos 61
Figura 9: Aplicação Fórmula1.
As interações podem ser feitas pressionando-se as teclas 1, 2 ou 3 do
dispositivo. O uso da tecla 1 resulta na apresentação de informações sobre
pilotos de fórmula 1. No caso do uso da tecla 2, informações sobre as escuderias
são exibidas. Já o uso da tecla 3 mostra a pista de Interlagos. Em todos os
casos, o vídeo passa a ocupar um quarto de tela, quando uma nova opção de
interação é exibida, como pode ser visto na Figura 10.
Testes Sistêmicos 62
Figura 10: Os três casos de interação da aplicação Fórmula1.
Ao se pressionar a tecla 9, a aplicação volta ao estado inicial.
Os exibidores usados na aplicação Fórmula 1 foram os de vídeo e
imagem. A grande maioria dos problemas tidos com esses exibidores foram
encontrados e solucionados durante a fase de testes feita com a aplicação em
questão. No caso do exibidor de imagem, foi observada a limitação dos tipos de
imagens suportados, como descrito no Capítulo 3. Além dessa limitação, o
exibidor de imagem não apresentou muitos problemas.
O exibidor de vídeo mostrou-se mais problemático. O maior problema
observado ocorreu porque a função de Open de vídeo, no Symbian, é
assíncrona. Logo depois de ordenar a abertura de um vídeo, através da
chamada à função Open, a máquina de apresentação solicita informações do
exibidor, como o tempo de duração e o volume. Nesse momento, pode ser que o
vídeo não tenha sido completamente carregado, o que causaria um erro.
A forma mais simples de se resolver esse problema é aguardar até que a
função Open termine o seu processamento e, somente então, continuar a
execução. Symbian oferece uma API que é capaz de fazer isso, ou seja, ela
provê uma forma de se aguardar pelo término de funções assíncronas. Essa API
Testes Sistêmicos 63
é, entretanto, complexa, de uso restrito, o que exige um bom conhecimento dos
Actives Objects. Apesar da sua complexidade, o uso dessa API solucionou o
problema adequadamente.
Como a API do exibidor de vídeo é muito similar à do exibidor de áudio,
acredita-se que muitos dos problemas que poderiam ocorrer na implementação
do exibidor de áudio foram evitados durante a fase dos testes em questão.
Erros no módulo Conversor também foram encontrados. Os maiores
problemas foram aqueles relacionados ao novo procedimento de parser e ao
tratamento das tags dependentes. Esses erros foram corrigidos e nenhum outro
problema referente aos procedimentos descritos foi encontrado nesse ou em
outros testes.
Durante a execução da aplicação Formula1, também foi possível perceber
o problema do uso das threads no Symbian. As imagens demoravam muito
tempo para serem exibidas, mesmo sem a apresentação do vídeo. Foi nesse
momento que se iniciou o estudo para a substituição das threads pelos Active
Objects. Quando a substituição foi feita, o problema foi solucionado e a aplicação
passou a ser apresentada eficientemente.
Foi também durante a execução da aplicação Formula1 que ficou evidente
a limitação da soma total das mídias que poderiam ser apresentadas ao mesmo
tempo em uma aplicação NCL. As três imagens que representam as opções de
interação ocupavam, inicialmente, muito espaço de memória. Por causa disso, a
soma dos tamanhos dos conteúdos acabava sendo muito grande, e a execução
da aplicação no dispositivo era finalizada por falta de recursos.
4.2. Matrix
A segunda aplicação desenvolvida e testada na implementação do Ginga-
NCL para dispositivos portáteis foi a Matrix_Mobile. O objetivo principal dessa
aplicação foi testar o sincronismo temporal. Ao ser iniciada, a aplicação exibe um
trecho do filme Matrix em toda a área disponível do dispositivo, como pode ser
visto na Figura 11.
Testes Sistêmicos 64
Figura 11: Aplicação Matrix_Mobile.
Em um determinado momento, um dos protagonistas mostra uma pilha.
Nesse instante, a aplicação reduz o tamanho do vídeo e apresenta, no espaço
restante, uma propaganda de pilha por um determinado período de tempo.
Quando esse tempo termina, a propaganda é removida e o vídeo é restaurado
ao seu tamanho original. A Figura 12 ilustra esse cenário.
Figura 12: Primeiro caso de sincronismo da aplicação Matrix_Mobile.
Em um outro momento, o mesmo ator fica próximo à câmera, realçando os
seus óculos. Nesse instante, o vídeo é reduzido a fim de oferecer espaço para
uma opção de interação, que fica disponível por um período fixo tempo. Depois
desse tempo, a imagem é removida, o tamanho do vídeo é restaurado e o
Testes Sistêmicos 65
usuário não poderá mais realizar a interação. Esse cenário é apresentado na
Figura 13.
Figura 13: Segundo caso de sincronismo da aplicação Matrix_Mobile (Sem interação).
Se o usuário optar por fazer a interação, realizada ao se pressionar a tecla
1, o vídeo terá as suas dimensões ainda mais reduzidas e uma propaganda de
óculos escuros será apresentada. Poucos segundos depois, a propaganda é
removida e o vídeo é restaurado ao seu tamanho original. A Figura 14 ilustra
esse cenário.
Figura 14: Segundo caso de sincronismo da aplicação Matrix_Mobile (Com interação).
Os exibidores usados nessa aplicação foram os de imagem e vídeo.
Nenhum problema novo foi observado para esses exibidores.
Como já mencionado, o objetivo do teste feito com o uso da aplicação
Matrix_Mobile foi verificar se o sincronismo estava funcionando corretamente.
Foi nesse momento, portanto, que se observou o problema do tratamento das
âncoras temporais, descrito na Seção 3.6. Depois que esse problema foi
solucionado, a aplicação Matrix_Mobile passou a funcionar corretamente, e
nenhum outro erro relevante foi encontrado.
Testes Sistêmicos 66
4.3. Carnaval
A terceira aplicação desenvolvida e testada foi a Carnaval. O seu objetivo
foi realizar o uso mais intenso do sincronismo e forçar um pouco mais o uso de
recursos. Quando iniciada, Carnaval exibe um vídeo, em tela cheia, de uma
escola tocando o seu samba-enredo, como pode ser visto na Figura 15.
Figura 15: Aplicação Carnaval.
Depois de um curto período de tempo, o vídeo tem o seu tamanho
reduzido e o espaço restante é preenchido com duas informações: a legenda do
samba-enredo sincronizada com o vídeo e duas opções de interação. A Figura
16 ilustra essa situação.
Testes Sistêmicos 67
Figura 16: Aplicação Carnaval com legenda e com as duas opções de interação.
A legenda é composta por trinta imagens sincronizadas com o vídeo ao
longo do tempo. Uma das interações é ativada pela tecla 1 e a outra pela 2. A
primeira interação exibe a bandeira da escola de samba e a segunda exibe uma
foto do intérprete, como pode ser visto na Figura 17.
Testes Sistêmicos 68
Figura 17: Os dois casos de interação da aplicação Carnaval.
Em ambos os casos, uma nova opção de interação — ativada pela tecla 9
— é oferecida para permitir ao usuário voltar às opções de interação iniciais.
Nenhum problema relevante foi encontrado com a execução da aplicação
Carnaval. O sincronismo da legenda funcionou corretamente e de forma
eficiente. Não foi observada perda de sincronismo nem mesmo quando as
interações eram muito exercitadas. Apesar de ser uma aplicação pesada, o seu
funcionamento se deu de forma adequada e eficiente.
Testes Sistêmicos 69
4.4. Exibidor HTML com Canal de Retorno
A última aplicação testada não foi baseada em nenhum tema. O seu
objetivo foi o de apenas testar a integração com o exibidor HTML, e o
funcionamento do recurso de foco e seleção da NCL. Essa aplicação,
diferentemente das apresentadas anteriormente, só foi testada em um dos
dispositivos disponíveis. Isso porque o outro não possuía uma interface de rede
a ser usada com o objetivo de se estabelecer uma conexão com a Internet
necessária para o teste do exibidor de HTML. Maiores detalhes sobre os
dispositivos são apresentados no Apêndice A desta dissertação.
Ao ser iniciada, a aplicação em questão divide a tela do dispositivo em
dois. Na parte superior é exibida uma página HTML e, na parte inferior, quatro
imagens de botões, como pode ser observado na Figura 18.
Figura 18: Aplicação 4.
É possível navegar com o foco entre todos os cinco elementos da
aplicação. A navegação dentro da página HTML se dá após ela ter sido
selecionada. Na aplicação em questão, quando um elemento está focado, uma
borda azul é desenha em seu contorno. Já quando o elemento é selecionado, a
cor verde é aplicada à borda. A Figura 19 mostra o momento em que a página
HTML está focada, depois a sua seleção e, por fim, a navegação dentro dela.
Testes Sistêmicos 70
Figura 19: Seleção e uso da página HTML.
Em qualquer momento, a seleção pode ser desfeita, possibilitando
novamente a navegação de foco entre os elementos da aplicação.
Cada uma das quatro imagens também podem ser selecionadas. O efeito
causado é a exibição momentânea de uma outra imagem que, em seguida, é
substituída pela imagem original. Isso permite a criação de efeitos simples de
animação. No caso da aplicação em questão, o efeito gerado é o de um botão
sendo pressionado, como exemplificado pela Figura 20.
Testes Sistêmicos 71
Figura 20: Botão pressionado.
A seleção da imagem que se encontra no canto inferior direito causa o
término da aplicação. Já a seleção das outras imagens inicia diferentes
conteúdos de áudio.
Os exibidores usados na aplicação foram os de imagem, áudio e HTML. O
exibidor de áudio praticamente não ofereceu problemas, assim como o de
imagem que já havia sido testado previamente. Já o exibidor de HTML causou
muitos problemas. O maior deles, entretanto, é o que fazia com que uma lista de
conexões fosse apresentada ao usuário. Isso é feito porque a API que trata das
páginas HTML não seleciona uma conexão padrão para estabelecer
comunicação com a Internet. Assim, existe a necessidade de se perguntar ao
Testes Sistêmicos 72
usuário qual conexão deve ser usada. O problema que ocorreu deveu-se ao fato
que, no Symbian, normalmente uma mesma camada gráfica é usada para se
desenhar quaisquer elementos na tela. O uso de janelas separadas, onde a
exibição de um elemento em uma janela não interfere na outra, é evitado, pois
exigiria o uso de mais de um elemento Window. Como já foi explicado na Seção
3.7, o uso de Windows não é recomendado. Dessa forma, a API da página
HTML mostra a lista de conexões por cima da aplicação NCL que está sendo
apresentada.
A solução mais simples para esse problema foi implementar uma forma de
se selecionar uma conexão padrão para a API, evitando, com isso, que a lista
fosse apresentada. Uma conexão deve, então, ser inicialmente estabelecida e
entregue a API. Essa solução funcionou no emulador, mas não foi suficiente. No
dispositivo testado, a API parecia ignorar a conexão estabelecida e voltava a
apresentar a lista ao usuário.
Uma segunda solução foi fazer com que a API em questão lançasse a lista
de conexões antes da aplicação NCL ser efetivamente iniciada. Assim, a lista é
apresentada, o usuário seleciona a opção mais conveniente, a tela é limpa e a
aplicação NCL pode, então, ser iniciada sem problemas. Isso resolveu o
problema causado pela API que tratava da página HTML. Essa API apresentou,
ainda, outros problemas menos relevantes que foram tratados de forma
apropriada.
A implementação do exibidor de HTML foi, portanto, como já descrito no
Capítulo 3, uma das mais complicadas. O tratamento do recurso de foco e
seleção, por outro lado, funcionou corretamente e causou poucos problemas.
5 Conclusões e Trabalhos Futuros
Este trabalho apresenta a primeira implementação de referência do Ginga-
NCL para dispositivos portáteis, que foi baseada em sua implementação para
terminais fixos apresentada resumidamente na Seção 3.1.
Antes de iniciar a implementação, foi necessário escolher uma plataforma
de desenvolvimento para dispositivos portáteis adequada. A Seção 2.3
apresentou um estudo comparativo dos sistemas operacionais e das suas
respectivas plataformas de desenvolvimento. Chegou-se à conclusão que o
sistema operacional Symbian, juntamente com a sua plataforma de
desenvolvimento nativa, era a melhor opção para a realização de uma primeira
implementação de referência do Ginga-NCL para os dispositivos portáteis.
Durante a realização dessa implementação foram encontrados diversos
problemas. Esses problemas são apresentados no Capítulo 3 desta dissertação
e têm as suas várias soluções apresentadas, analisadas e, quando havia mais
de uma solução para um mesmo problema, comparadas. Por fim, foram
descritas as soluções que foram realmente adotadas.
A implementação resultante de todo o trabalho descrito nesta dissertação
foi testada em um emulador de dispositivos portáteis Symbian, e em dois
dispositivos portáteis diferentes. Em ambos os casos, o funcionamento do
Ginga-NCL se deu de modo correto e eficiente, sem a necessidade de se
realizar qualquer modificação na especificação. Isso mostra que a especificação
do Ginga-NCL é suficientemente leve para ser embarcada em dispositivos
portáteis — mesmo que estes não tenham sido desenvolvidos para serem
usados especificamente como receptores de TV — e que é, portanto, adequada
a esse tipo de dispositivo. Assim, o principal objetivo almejado pelo estudo
apresentado nesta dissertação foi alcançado. A demonstração de que a
especificação do Ginga-NCL é adequada ao contexto dos dispositivos portáteis
também é a maior contribuição oferecida pelo estudo apresentado.
Uma outra contribuição que pode ser citada é decorrente da nova
implementação do módulo Conversor. Essa implementação demonstrou que o
uso do parser DOM é desnecessário para o processamento de documentos NCL
Conclusões e Trabalhos Futuros 74
— tanto no escopo dos dispositivos portáteis quanto para os terminais fixos — e
que, por isso, o uso do parser SAX é mais vantajoso.
Salvo as contribuições citadas, algumas outras conclusões podem ser
tiradas do trabalho apresentado. Acredita-se que muitos dos problemas
observados e apresentados nesta dissertação também podem ocorrer em outras
plataformas de desenvolvimento, em especial naquelas que forem fechadas. Os
resultados aqui obtidos, portanto, podem ser usados como referência em
implementações futuras do Ginga-NCL feitas em outras plataformas de
desenvolvimento.
A arquitetura da implementação de referência do Ginga-NCL, apresentada
na Seção 3.1, foi desenvolvida com o objetivo de facilitar o procedimento de
porte para diversas plataformas. Essa arquitetura foi, portanto, desenvolvida de
forma modular e abstrata o suficiente para que as partes específicas de
plataforma pudessem ser isoladas das partes gerais e independentes de
plataforma. Entretanto, nenhum porte da implementação havia sido realizado, ou
seja, a arquitetura em questão ainda não tinha sido validada nessa questão. O
resultado do trabalho apresentado nesta dissertação foi, de fato, o primeiro
passo para realizar essa validação.
Ao longo de toda a implementação do Ginga para dispositivos portáteis,
foram encontradas, na implementação de referência, abstrações no uso de
recursos específicos de plataforma. Essas abstrações permitiram que apenas
parcelas específicas e pontuais da implementação de referência tivessem que
ser modificadas, mantendo intacta a já funcional estrutura genérica do
middleware. Isso facilita o procedimento de porte na medida em que o
funcionamento geral do middleware não precisa ser modificado, evitando erros e
permitindo que um maior foco pudesse ser dado às especificidades da
plataforma. A modularização da arquitetura também é um fator que contribuiu
para o porte. Na implementação apresentada, por exemplo, o módulo Conversor
foi quase que completamente modificado sem que isso interferisse no
funcionamento do middleware como um todo. Isso só foi possível graças à boa
delineação dos módulos na arquitetura. Assim, é possível concluir, através do
estudo apresentado, que a forma como a arquitetura da implementação de
referência do Ginga-NCL foi desenvolvida de fato facilita o procedimento de
porte.
Existem alguns possíveis trabalhos futuros que poderão ser desenvolvidos
a fim de se incrementar o trabalho apresentado nesta dissertação. O primeiro
trabalho sugerido diz respeito ao procedimento de parser do Ginga-NCL. Nesta
Conclusões e Trabalhos Futuros 75
dissertação foi apresentada a substituição do parser DOM pelo SAX, levando-se
em consideração o fato de que testes realizados em (Violleau, 2002), (Oren,
2002), (Devsphere, 2007) e (Franklin, 2007) entre esses dois tipos de parser
indicam, de forma genérica, uma eficiência maior por parte do SAX. Entretanto,
nenhum estudo comparativo foi feito entre uma implementação do módulo
Conversor que use SAX e outra que use DOM. Seria interessante, portanto,
realizar esse estudo a fim de se ter uma comparação entre o DOM e o SAX
dentro do contexto do Ginga-NCL. Um outro trabalho que pode ser feito em
relação ao parser é implementar o tratamento dos comandos de edição ao vivo,
que não foi feito na versão do Ginga-NCL para dispositivos portáteis
apresentada.
Um segundo trabalho futuro é a implementação do modelo para a
especificação temporal de aplicações hipermídia descrito em (Costa e Soares,
2007). Esse modelo viabiliza, dentre outras coisas, a interrupção da
apresentação de uma aplicação NCL como um todo e a sua posterior retomada
a partir do mesmo instante temporal. Considerando, ainda, o universo dos
dispositivos portáteis, uma vantagem é que esse modelo foi especificado de tal
forma que é possível descartar parcelas suas que já tenham sido usadas ou que
nunca mais serão utilizadas. Isso pode ser feito em qualquer momento de uma
apresentação NCL, o que possibilita a otimização do uso dos recursos de
memória, que são muito limitados na maioria dos dispositivos portáteis.
Um outro trabalho sugerido é a execução testes de desempenho na
implementação de referência do Ginga-NCL para dispositivos portáteis,
verificando o nível do consumo de recursos utilizados, como bateria, memória e
CPU. O objetivo é verificar a carga imposta pela implementação ao sistema
operacional, determinando se, por exemplo, outras aplicações podem ser
executadas ao mesmo tempo em que uma aplicação NCL é exibida.
É sugerida, também, a implementação da funcionalidade de adaptação da
NCL em função da disponibilidade de recursos do aparelho, o que não foi feito
na implementação apresentada nesta dissertação. Com essa funcionalidade, um
aplicação pode ser desenvolvida de maneira que funcione em dispositivos com
restrições de recursos diferentes.
Um outro trabalho que pode ser feito diz respeito aos exibidores de mídia.
Novos exibidores, o de texto e Lua, podem ser implementados e o exibidor de
imagem pode ser melhorado. A API específica de tratamento de texto em
Symbian possui documentação insuficiente e, até o término da implementação
que é apresentada neste estudo, era pouco utilizada — o que significa que
Conclusões e Trabalhos Futuros 76
poucas pessoas da comunidade de desenvolvimento sabiam como utilizá-la. A
melhor opção para o início da implementação desse exibidor é começar pela
busca de códigos exemplo que possam ser usados no entendimento do uso da
API Symbian de texto. Espera-se, portanto, que a implementação desse exibidor
ofereça alguns problemas. É incerto, entretanto, se a implementação do exibidor
de texto em outras plataformas de desenvolvimento também apresentarão
problemas.
No que diz respeito ao exibidor Lua, será necessário portar o interpretador
Lua, que é todo implementado em ANSI C, as interfaces do Ginga-NCL com
esse interpretador e algumas bibliotecas Lua desenvolvidas especificamente
para o Ginga-NCL. Em Symbian, portar o interpretador Lua não deve oferecer
muito trabalho por conta da existência das bibliotecas P.I.P.S. e Open C. Já em
plataformas fechadas, o ANSI C pode estar apenas parcialmente implementado,
ou nem sequer isso. Portar o interpretador Lua para esse tipo de plataforma
pode ser mais problemático. As interfaces e as bibliotecas feitas para o Ginga-
NCL, porém, possuem algumas características específicas de plataforma que
podem introduzir um nível de dificuldade maior, tanto no Symbian quanto em
qualquer outra plataforma.
O incremento ao exibidor de imagem é sugerido a fim de que ele possa
oferecer suporte à apresentação de outros tipos de imagem além da mbm. Será
necessário, entretanto, fazer uso de uma classe que converta outros tipos de
imagem, como png, bmp ou gif, em imagens mbm. Isso porque a classe
apresentada na Seção 3.7 capaz de carregar imagens no Symbian, a
CFbsBitmap, só consegue carregar imagens do tipo mbm. O problema é que a
documentação da classe que faz a conversão é confusa, e também existem
poucos exemplos do seu uso.
Por fim, o último trabalho futuro sugerido é a implementação dos módulos
Sintonizador, Filtro de Seções e Processador de Fluxos de Dados, que são
descritos na Seção 3.1, em uma plataforma com recepção SBTVD.
6 Referências Bibliográficas
ABNT/CEET-00:001.85. Televisão digital terrestre - Codificação de dados e
especificações de transmissão para radiofusão digital – Parte 2: Ginga-NCL para
receptores fixos e móveis – Linguagem de aplicação XML para codificação de
aplicações. Setembro 2007.
Babin, Steve, Harrison, Richard. Developing Software for Symbian OS An
Introduction to Creating Smartphone Applications in C++. Jonh Wiley & Sons Ltd,
2006.
Berenger, Francis Machado, Maia, Luiz Paulo. Arquitetura de Sistemas
Operacionais. 3ª edição. LTC, 2002.
Costa R.M.R., Soares L.F.G.. Modelo Temporal Hipermídia para Suporte a
Apresentações em Ambientes Interativos. Rio de Janeiro: PUC-Rio -
Departamento de Informática. 2007.
Cruz, Vitor Medina, Moreno, Marcio Ferreira, Luiz Fernando Gomes,
Soares. TV Digital Para Dispositivos Portáteis – Middlewares. Relatório Técnico;
Rio de Janeiro: PUC-Rio – Departamento de Informática, jan. 2008.
Devsphere. SAX versus DOM. Benchmark performed with Xerces and
Crimson. Disponível em: http://www.devsphere.com/xml/benchmark/method.html.
2007. Último acesso em Fevereiro de 2008.
directfb.org | Main. Disponível em: http://www.directfb.org/. mar. de 2008.
Último acesso em Março de 2008.
Digital TV Facts. DTV Guide Transmission. Disponível em:
http://dtvfacts.com/latest/250/as-digital-tv-reception-controversy-dims-e-vsb-gets-
another-look/. maio 2006. Último acesso em janeiro de 2008.
Farwick, Matthias, Hafner ,Michael. XML.com: XML Parser Benchmarks:
Part 1. Disponível em: http://www.xml.com/pub/a/2007/05/09/xml-parser-
benchmarks-part-1.html. Maio de 2007. Último acesso em Fevereiro de 2008.
Forum Nokia. Open C for S60:Increasing Developer Productivity, Version
1.2. mar 2007.
Franklin, Steve. XML Parsers: DOM and SAX Put to the Test. Disponível
em: http://www.devx.com/xml/Article/16922/1954?pf=true. 2007. Último acesso
em Fevereiro de 2008.
Referências Bibliográficas 78
Harrison, Richard et al. Symbian OS C++ for Mobile Phones. Volume 1.
John Wiley & Sons, 2003.
Harrison, Richard et al. Symbian OS C++ for Mobile Phones. Volume 2.
John Wiley & Sons, 2004.
Java Technology. Disponível em: http://java.sun.com/. Último acesso em
Setembro de 2007.
Jez, Marco. Disponível em:
http://marcoplusplus.blogspot.com/2007/05/stlport-for-symbian-os-released.html.
maio 2007. Último acesso em Fevereiro de 2008.
Moreno, Marcio Ferreira. Um Middleware Declarativo para Sistemas de TV
Digital Interativa. Dissertação de mestrado; Rio de Janeiro: PUC-Rio –
Departamento de Informática, abril de 2006.
Morley, Jason. Leaves and Exceptions Version: 1.3.1. Published by the
Symbian Developer Network, set 2007.
Nokia. Device Details -- Nokia 5700 XpressMusic. Disponível em:
http://www.forum.nokia.com/devices/5700_XpressMusic. 2008. Último acesso em
Julho de 2008.
Nokia. Device Details -- Nokia N81. Disponível em:
http://www.forum.nokia.com/devices/N81. 2008. Último acesso em Julho de
2008.
Nokia. S60 Platform SDKs for Symbian OS, for C++. Disponível em:
http://www.forum.nokia.com/info/sw.nokia.com/id/4a7149a5-95a5-4726-913a-
3c6f21eb65a5/S60-SDK-0616-3.0-mr.html. 2008. Último acesso em Fevereiro de
2008.
Nokia. Open C SDK Plug-In for S60 3rd Edition SDKs, for Symbian OS, for
C++. Disponível em: http://www.forum.nokia.com/info/sw.nokia.com/id/91d89929-
fb8c-4d66-bea0-227e42df9053/Open_C_SDK_Plug-In.html. 2008. Último acesso
em Fevereiro de 2008.
Nokia. Carbide.c++ v1.2, the development tool for C++ for Symbian OS and
Open C developers. Disponível em:
http://www.forum.nokia.com/info/sw.nokia.com/id/dbb8841d-832c-43a6-be13-
f78119a2b4cb.html. 2008. Último Acesso em Fevereiro de 2008.
Oren, Yuval. SAX Parser Benchmarks. Disponível em:
http://piccolo.sourceforge.net/bench.html. 2002. Último acesso em Fevereiro de
2008.
Referências Bibliográficas 79
SDN. P.I.P.S. - Symbian Development Public Wiki – SDN Wiki. Disonível
em: http://developer.symbian.com/wiki/display/pub/P.I.P.S. Fevereiro de 2008.
Último acesso em Fevereiro de 2008.
Silva , Heron V. O., Rodrigues, Rogério Ferreira, Soares, Luiz Fernando
Gomes. Frameworks para Processamento de Documentos XML. Rio de Janeiro:
Departamento de Informática, PUC-Rio. 2005.
Smil 2.1 – Timing and Syncronization. Disponível em:
http://www.w3.org/TR/2005/REC-SMIL2-20051213/smil-timing.html. dec. 2005.
Último acesso em fevereiro de 2007.
Soares, L.F.G., Rodrigues, R.F., Moreno, M.F. Ginga-NCL: the Declarative
Environment of the Brazilian Digital TV System. Rio de Janeiro: PUC-Rio -
Departamento de Informática. abril 2007.
SOARES, L.F.G., RODRIGUES, R.F., MUCHALUAT-SAADE, D.C. Modelo
de Contextos Aninhados – versão 3.0, Relatório Técnico, Laboratório TeleMídia,
Departamento de Informática, PUC-Rio, 2003.
Stichbury, Jo. Symbian OS Explained. Effective C++ Programming for
Smartphones. John Wiley & Sons Ltd, 2004.
STLPort. Disponível em: http://www.stlport.org/. 2001. Último acesso em
Fevereiro de 2008.
Symbian Ltd. P.I.P.S. Home - P.I.P.S. - Symbian Wiki. Disponível em:
http://developer.symbian.com/wiki/display/oe/P.I.P.S.+Home. fev de 2008. Último
acesso em Fevereiro de 2008.
Symbian Ltd. Using Symbian OS GETTING STARTED, 2007 2nd edition.
2-6 Boundary Row, London SE1 8HP, UK, jan. de 2007.
Symbian Ltd. Using Symbian OS P.I.P.S. fev de 2007.
Symbian Ltd, Nokia. S60 3rd Edition SDK for Symbian OS, Supporting
Feature Pack 1, for C++. SDK Help. out. de 2006.
Violleau, Thierry. Java Technology and XML-Part Two. Disponível em:
http://java.sun.com/developer/technicalArticles/xml/JavaTechandXML_part2/.
Março 2002. Último Acesso em Fevereiro de 2008.
Apêndice A – Instalação e Dispositivos Testados
Este apêndice tem como objetivo servir como um manual para a criação do
ambiente necessário à compilação dos pacotes Ginga-NCL, bem como para a
execução da aplicação resultante em um emulador de dispositivo Symbian ou
para a instalação dessa aplicação em um dispositivo Symbian real. Ao final,
também serão apresentados os dispositivos onde o Ginga-NCL foi instalado e os
resultados obtidos.
Todas as ferramentas Symbian são disponibilizadas, oficialmente, apenas
nas plataformas Windows XP e Windows 2000. Sendo assim, todas as
instalações especificadas por esta seção devem ser feitas em um desses dois
sistemas.
O primeiro elemento que precisa ser instalado para a criação do ambiente
necessário a compilação e execução do Ginga-NCL é o S60 3rd Edition SDK F1,
que é um SDK específico para a versão 9.2 do sistema operacional Symbian.
Esse SDK pode ser encontrado em (Nokia, 2008c). O procedimento de
instalação é simples e envolve a leitura e aceitação da licença, além de algumas
escolhas típicas de instalação. Em seguida, precisam ser instaladas as
bibliotecas P.I.P.S., Open C e STLPort para Symbian, que podem ser
encontradas, respectivamente, em (SDN, 2008), (Nokia, 2008d) e (Jez, 2007). A
primeira foi desenvolvida pela Symbian e é usada na realização do porte de
códigos redigidos em C. A segunda é uma extensão (superset) da P.I.P.S., ou
seja, oferece uma capacidade de porte ainda maior, mas funciona somente para
a plataforma do Symbian S60. A terceira é um porte, feito por um membro da
comunidade Symbian, de uma implementação da biblioteca STL que foi
originalmente desenvolvida para dispositivos embedded. A necessidade dessas
API’s foi explicada na seção 3.2. O procedimento de instalação dessas
bibliotecas pode ser resumido nas seguintes etapas:
• Descompactar os arquivos zip do PIPS do Open C e da STLPort
em três pastas separadas;
• Copiar o conteúdo da pasta epoc32 presente em cada uma das três
pastas e colá-lo dentro da pasta
<Diretório_de_Instalação_do_SDK_3rd_Edition_FP1>\Epoc32\.
Quando solicitado, é preciso selecionar a opção de substituir todos
os arquivos repetidos pelos os que estão sendo copiados.
Apêndice A – Instalação e Dispositivos Testados 81
Depois que essas três bibliotecas estiverem instaladas, o próximo passo
consiste em instalar um ambiente de desenvolvimento apropriado. Como o
Carbide C++ Free 1.2 foi utilizado ao longo de todo o processo de
desenvolvimento do Ginga-NCL, e como os projetos da implementação Ginga-
NCL para dispositivos portáteis estão no formato dessa ferramenta, recomenda-
se o uso do Carbide C++ Free 1.2 ou, ainda, uma versão sua paga. O Carbide
C++ Free 1.2 pode ser encontrado em (Nokia, 2008e) e a sua instalação também
é trivial. Ressalta-se, entretanto, que, para o seu correto funcionamento, o
ActivePerl-5.6.1.635 deve ser instalado. Se uma versão mais nova ou mais
antiga desse elemento for instalada, o Carbide não funcionará corretamente.
Para fazer uso das bibliotecas P.I.P.S. Open C e STLPort nessa ferramenta, os
seguintes procedimentos devem ser realizados:
1. Dada a existência de um projeto Carbide 1.2, abrir o arquivo
<Nome_do_Projeto>.mmp que se encontra dentro da pasta "group"
do projeto. Nele são definidos todos os includes e as bibliotecas
usadas pelo projeto;
2. Adicionar "/epoc32/include/stdapis" em System Include para fazer
uso do PIPS e do OpenC;
3. Adicionar "/epoc32/include/stlport" em System Include para fazer
uso da STLPort;
4. Adicionar a "libc" e a "stlport_s" na guia de bibliotecas. A primeira
deve ser ligada dinamicamente enquanto que a segunda deve ser
ligada estaticamente.
A implementação do Ginga-NCL é dividida em seis pacotes: telemidia-
util_Symbian, ncl30_Symbian, ncl30-converter_Symbian, gingacc-
io_Symbian, gingacc-player-Symbian e gingancl_Symbian. O primeiro
implementa algumas funções auxiliares que são muito usadas nos outros
pacotes. O segundo, a estrutura NCM da qual o documento NCL deverá ser
convertido, e o terceiro pacote é o que fica responsável por realizar a conversão
propriamente dita, sendo nele, portanto, onde é encontrado o parser SAX. O
quarto pacote implementa o controle de tela e dos gráficos, enquanto que o
quinto, os exibidores. O último pacote corresponde a máquina de apresentação,
e é, portanto, aquele que gera a aplicação Ginga-NCL.
Para importar um projeto Symbian no Carbide C++, basta selecionar o
menu File->Import dessa ferramenta para que uma janela de importação
apareça com uma série de opções, incluído duas para projetos Symbian: a
“Symbian OS Bdl.inf file” e a “Symbian OS Executable”. A primeira opção deve
Apêndice A – Instalação e Dispositivos Testados 82
ser selecionada. Em seguida, será necessário selecionar um arquivo bdl.inf para
ser importado, que normalmente encontra-se dentro da pasta “group” de um
projeto Symbian. Esse tipo de arquivo guarda informações sobre a organização
do projeto. Depois disso, será preciso escolher as configurações de “Build”.
Cada SDK oferece duas opções desse tipo, uma que gera binários para
execução no emulador e outra para execução nos dispositivos portáteis. Ambas
devem ser selecionadas. Em seguida, deverão ser escolhidos os arquivos de
compilação que devem ser importados. Todos os disponíveis devem ser
selecionados. Por fim, será solicitado o nome a ser dado para o projeto
importado no Carbide C++ e em que pasta ele será copiado. Recomenda-se
aceitar os valores padrões. Esse procedimento deve ser feito para todos os seis
pacotes do Ginga-NCL para que a sua compilação possa ser efetuada.
A compilação pode ser feita de forma a gerar binários tanto para o
emulador quanto para dispositivos Symbian S60. Para escolher uma dessas
opções, é necessário clicar com o botão direito do mouse no projeto e ir em
Active Build Configuration. Serão dadas as duas opções de Build: “Emulator
Debug” e “Phone Release”, sendo que a primeira gera um binário do programa
para o emulador, e a segunda, o binário para um dispositivo Symbian S60. Seja
qual for a opção escolhida, a ordem correta de compilação dos pacotes é
telemidia-util_Symbian, ncl30_Symbian, ncl30-converter_Symbian,
gingacc-io_Symbian, gingacc-player-Symbian e gingancl_Symbian,
respectivamente.
Para executar o Ginga-NCL no emulador provido pelo SDK, basta clicar
com o botão direito do mouse no projeto gingancl_Symbian e selecionar a
opção RunAs-> Run Symbian OS Application. O emulador será iniciado e a
aplicação Ginga-NCL poderá ser encontrada dentro do sub-menu “Installed” do
menu do celular emulado.
Para instalar a aplicação Ginga-NCL em um dispositivo S60 que possua o
Symbian 9.2, é necessário usar o arquivo de instalação .sisx que é gerado
dentro da pasta sis do pacote gingancl_Symbian após o término da compilação.
Para realizar a instalação, um software de sincronismo, como o Nokia PC Suit,
deve ser usado com o objetivo de se estabelecer uma conexão entre um
dispositivo portátil e um computador que possua o arquivo de instalação sisx.
Uma vez estabelecida essa conexão, basta clicar duas vezes sobre o arquivo
.sisx de instalação do Ginga-NCL que um wizzard de instalação vai aparecer na
tela do dispositivo conectado. Por fim, basta seguir as instruções do wizzard e a
aplicação será instalada. As bibliotecas P.I.P.S. e Open C também precisam ser
Apêndice A – Instalação e Dispositivos Testados 83
instaladas no dispositivo. Os arquivos de instalação dessas bibliotecas podem
ser encontrados na pasta S60Opensis do arquivo .zip baixado de (Nokia, 2008d).
Antes de executar o Ginga-NCL, tanto no dispositivo como no emulador, é
preciso criar uma pasta de nome “Ginga” na raiz do sistema. No dispositivo
portátil, a raiz é a pasta “Data”. No emulador, a raiz do dispositivo é emulada na
pasta <Diretório_de_Instalação_do_SDK_3rd_Edition>\Epoc32\winscw\c\Data. A
pasta “config”, que se encontra dento da pasta “data” do pacote
gingancl_Symbian, deve ser colocada dentro da pasta “Ginga” recém criada. A
“config” possui uma série de arquivos de configuração do Ginga-NCL que são
necessários para a sua execução. Dentro da pasta Ginga também devem ser
colocadas todas as aplicações interativas e um arquivo de nome ginga.conf.
Esse arquivo deve possuir, em seu conteúdo, referências às ncls das aplicações
interativas que se encontram dentro da pasta Ginga. Cada linha desse arquivo
deve possuir apenas uma referência para uma ncl. Por exemplo, imagine que
existam duas aplicações interativas dentro da pasta “Ginga”: matrix e formula1.
Dentro da pasta “matrix” existe uma ncl chamada “matrix.ncl”, e dentro da pasta
“formula1”, uma outra ncl chamada “formula1.ncl”. Nesse contexto, o arquivo
ginga.conf deverá ser criado da seguinte forma:
matrix/matrix.ncl
formula1/formula1.ncl
Dessa forma, quando o Ginga-NCL for executado, uma lista com essas
duas aplicações será apresentada. Aquela que for selecionada será tocada pelo
middleware.
A implementação do Ginga-NCL para dispositivos portáteis foi instalada e
testada em dois dispositivos: o Nokia 5700 Express Music e o Nokia N81 1G.
O Nokia 5700 Express Music possui 369 Mhz e 64 Mb de memória RAM
com aproximadamente 18 Mb livres para o uso em aplicações. Já o Nokia N81
1G possui 369 Mhz e 96 Mb de memória RAM com aproximadamente 42 Mb
livres para o uso em aplicações. Ambos os aparelhos suportam os seguintes
formatos de vídeo e áudio: 3GPPH.263, H.264/AVC, MPEG-4 AAC, eAAC+,
MP3, MP4, M4A, WMA, AMR-NB, AMR-WB, Mobile XMF, SP-MIDI, MIDI Tones
(poly 64) e WAV (Nokia, 2008a) e (Nokia, 2008b). Somente o Nokia N81 1G
possui suporte a WLAN, que é oferecido através de interfaces 802.11 b/g, WPA
ou WPA2 (AES/TKIP) (Nokia, 2008b).
Apêndice A – Instalação e Dispositivos Testados 84
Em ambos dispositivos testados, o Ginga-NCL funcionou corretamente
sem qualquer problema aparente de desempenho e da mesma forma que no
emulador.