adaptaÇÃo de servidor proxy para...
TRANSCRIPT
ADAPTAÇÃO DE SERVIDOR PROXY PARA
TRANSMISSÃO DE VÍDEO SEGMENTADO
EM MULTI-TAXAS
Carlos Alexandre Rossi
Projeto de Graduação apresentado ao Curso de
Engenharia Eletrônica e de Computação da Escola
Politécnica, Universidade Federal do Rio de Janei-
ro, como parte dos requisitos necessários à obten-
ção do título de Engenheiro.
Co-orientadores: Aloysio de Castro Pinto Pedroza
Claudio Luís de Amorim
Rio de Janeiro
Agosto de 2014
3
UNIVERSIDADE FEDERAL DO RIO DE JANEIRO
Escola Politécnica – Departamento de Eletrônica e de Computação
Centro de Tecnologia, bloco H, sala H-217, Cidade Universitária
Rio de Janeiro – RJ CEP 21949-900
Este exemplar é de propriedade da Universidade Federal do Rio de Janeiro, que
poderá incluí-lo em base de dados, armazenar em computador, microfilmar ou adotar
qualquer forma de arquivamento.
É permitida a menção, reprodução parcial ou integral e a transmissão entre
bibliotecas deste trabalho, sem modificação de seu texto, em qualquer meio que esteja
ou venha a ser fixado, para pesquisa acadêmica, comentários e citações, desde que sem
finalidade comercial e que seja feita a referência bibliográfica completa.
Os conceitos expressos neste trabalho são de responsabilidade do autor.
4
DEDICATÓRIA
Dedico este trabalho a todos os estudantes de Engenharia do Brasil,
principalmente aos que moram longe de suas faculdades e aos que escolheram a
especialidade de Eletrônica, certamente uma das mais difíceis.
Formar-se em Engenharia Eletrônica não é tarefa das mais simples, e no meu
caso a conclusão deste projeto teria sido impossível sem o apoio dos meus amigos e da
minha família, que acompanharam, e ainda o fazem, a minha luta diária para concluí-lo,
junto ao meu curso. Por estes e outros motivos, também lhes dedico este trabalho.
5
AGRADECIMENTO
Gostaria de agradecer a todos que me apoiaram durante a graduação em
Engenharia Eletrônica e que tornaram possível a realização deste projeto de fim de
curso.
Inicialmente, agradeço a meus pais, que sempre priorizaram a minha educação
acima de tudo, realizando todos os sacrifícios possíveis para que eu pudesse ingressar
numa das melhores universidades do Brasil que é a UFRJ. Estendo este agradecimento à
minha avó materna e à minha tia, que me ajudaram nos momentos mais difíceis.
Em seguida, agradeço a todos os meus amigos, que acreditaram em mim durante
todo o meu curso e que se fizeram presentes para compartilhar os meus sucessos e me
ajudar a me reerguer nos fracassos. Em particular, agradeço ao Allan Freitas e à Isabela
Apolinário, por serem meus colegas de curso e estarem mais presentes quando eu pensei
em desistir.
Também agradeço ao mestrando Nelson Perez, responsável pelo projeto original
do servidor proxy, e ao Prof. Lauro Whately, ambos membros do Laboratório de
Computação Paralela e Sistemas Móveis (COMPASSO) da CoPPE/UFRJ, que
confiaram a mim a oportunidade de dar continuar a este projeto e me auxiliariam em
tudo o que eu precisei.
Meus agradecimentos também vão para meus orientadores Prof. Claudio
Amorim, coordenador do Laboratório COMPASSO, e Prof. Aloysio Pedroza, que
ministrou a disciplina de Sistemas Operacionais durante o meu curso de graduação, área
na qual se inclui o tema deste projeto. Também incluo aqui os membros da banca, Prof.
Heraldo Almeida e Prof. Sérgio Villas-Boas, que se dispuseram prontamente a avaliar
este projeto, mesmo com o horário da apresentação não sendo dos mais confortáveis.
Por fim, agradeço a todos os professores que tive ao longo da minha vida, dentro
e fora da UFRJ. Sem estes profissionais escolhidos pela mais nobre das carreiras, nada
do que conquistei na minha vida acadêmica e profissional teria sido possível. Em relação
à graduação, sou especialmente grato aos Profs. José Apolinário, Luiz Wagner, Jomar
Gozzi (meu orientador acadêmico) e Carlos José (coordenador do curso de graduação
em Engenharia Eletrônica e de Computação da UFRJ).
6
RESUMO
Palavras-Chave: HDS ; vídeo segmentado ; servidor proxy ; cache ; streaming
adaptativo.
Este trabalho finaliza o curso de Engenharia Eletrônica e de Computação da
UFRJ e consiste num conjunto de alterações para que um servidor proxy especializado
em streaming via HTTP passasse a lidar com pedidos de mídias codificadas em
múltiplas taxas – streaming adaptativo –, transmitidas segundo o padrão HDS. O
servidor proxy possui uma política de cacheamento específica, e as modificações
tratadas neste projeto a envolvem.
7
ABSTRACT
Key-words: HDS ; segmented video ; proxy server ; cache ; adaptive streaming.
This paper concludes the graduation in Electronic and Computation Engineering
at UFRJ, and it consists in modifying a proxy server specialized in streaming over
HTTP so it could deal with requests of medias presented at multiple representations –
adaptive streaming –, transmitted through HDS. The proxy server has an specific
caching policy, and it's within the modifications this paper describes.
8
SIGLAS
UFRJ – Universidade Federal do Rio de Janeiro
HTTP – Hyper-Text Transfer Protocol
HDS – HTTP Dynamic Streaming
XML – Extensible Markup Language
MSS – Microsoft Smooth Streaming
HLS – HTTP Live Streaming
MPEG – Motion Pictures Experts Group
DASH – Dynamic Adaptive Streaming over HTTP
Sumário
1 Introdução 12
1.1 - Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.2 - Delimitação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3 - Justificativa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4 - Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5 - Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6 - Descrição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2 O Arquivo de Manifest 16
2.1 - Justificativa para o uso do manifest . . . . . . . . . . . . . . . . . . . . 16
2.2 - Informações importantes do manifest . . . . . . . . . . . . . . . . . . 16
2.3 - Bootstrap Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4 - Segmentação do vídeo em HDS . . . . . . . . . . . . . . . . . . . . . . 21
3 Modificações no Servidor Proxy 23
3.1 - Classes e estruturas auxiliares . . . . . . . . . . . . . . . . . . . . . . . . 23
3.1.1 - A unidade de compilação f4mParser . . . . . . . . . . . . . . . . . 23
3.1.2 - A Estrutura manifestInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2 - Unidades de compilação modificadas . . . . . . . . . . . . . . . . . . 28
3.2.1 - proxy-conn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.2 - hub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.2.3 - Mcc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2.4 - cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8
3.2.5 - segment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.2.6 - metadata-fetcher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.2.7 - common.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.2.8 - Arquivo de dependências, Makefile . . . . . . . . . . . . . . . . . . 41
3.3 - Servidor proxy em execução . . . . . . . . . . . . . . . . . . . . . . . . . 41
4 Ferramentas Auxiliares 45
4.1 - Ferramentas para leitura do manifest . . . . . . . . . . . . . . . . . . . 45
2.2 - Wireshark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.3 - Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.4 - GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5 Resultados e Conclusões 51
6 Trabalhos Futuros 53
Bibliografia 55
A Exemplo de arquivo de manifest 56
9
11
Lista de Figuras
3.1 – Relação entre métodos da classe f4mParser . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2 – Relação entre unidades de compilação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 – Tríade identificadora dos Fragmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.4 – Primeiro ciclo de execução do servidor proxy . . . . . . . . . . . . . . . . . . . . . . . . 44
3.5 – Ciclo de métodos da classe Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.1 – Interface do GHex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.2 – Resultado da execução do Wireshark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
12
Lista de Tabelas
2.1 – Exemplo de tabela de entrada de Fragmentos . . . . . . . . . . . . . . . . . . . . . . . . 23
3.1 – Estrutura manifestInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
13
Capítulo 1
Introdução
1.1 – Tema
Este relatório é relativo à conclusão do curso de Graduação em Engenharia
Eletrônica e de Computação da Escola Politécnica da UFRJ. A ênfase do projeto sobre o
qual este documento discorre é a área de Computação.
O tema do trabalho é transmissão de vídeo pela internet, baseando-se na
implementação de um servidor proxy voltado para a transmissão de vídeo por
streaming.
1.2 – Delimitação
Com o aumento da banda disponível para as conexões através da internet, houve
um crescimento da demanda por conteúdo em vídeo, tanto da parte dos provedores de
conteúdo quanto de quem busca por este tipo de informação. Na última década, diversos
serviços foram desenvolvidos com o intuito de suprir esta demanda, entre elas a
tecnologia de streaming. Contudo, empresas líderes do segmento, como a Microsoft ©,
a Apple © e a Adobe ©, desenvolveram seus próprios protocolos para implementar estes
recursos. Este trabalho opta pela implementação da Adobe © num contexto de um
mercado ainda incerto, mas em franca expansão.
O protocolo de transmissão de vídeo segmentado por streaming utilizado é
aquele que se utiliza do próprio HTTP para estabelecer a comunicação entre o cliente e
o servidor, conhecido como HDS (HTTP Dynamic Streaming).
1.3 – Justificativa
Além do crescimento do número de usuários, a internet também se diversificou
em plataformas de acesso nas últimas duas décadas. Naturalmente, surgiram novas
necessidades em termos de acesso às diversas mídias existentes, sobretudo a vídeos. Um
provedor de conteúdo poderia desejar, por exemplo, que seu vídeo fosse assistido a
partir de um televisor de 42 polegadas, de um monitor de 17 polegadas, de um tablet e
de um smartphone.
No exemplo citado, a qualidade da mídia a ser transmitida cresce do smartphone
ao televisor, de modo que a velocidade de transmissão de dados e a banda necessária
acompanham este crescimento. Assim, uma mesma mídia precisa ser armazenada em
múltiplas representações pelo provedor de conteúdo para que esta demanda por diversas
plataformas seja atendida. Estas representações compreendem características gerais do
vídeo, como áudio, legenda e número de quadros por segundo, mas serão indicadas
através da taxa de transferência, ou seja, múltiplas representações serão consideradas
múltiplas taxas.
Neste contexto, surgem os vídeos multi-taxas, através dos quais uma mesma
mídia compreende múltiplas representações, e uma única destas deverá ser reproduzida
conforme critérios definidos pelo mecanismo de reprodução. Pode-se considerar que a
banda disponível é sempre um limitante, de modo que a tendência é de que seja
reproduzida a representação de maior qualidade que permita que o cliente assista o
vídeo sem interrupções.
Entretanto, como a banda disponível não é fixa, torna-se interessante que se
possa alternar entre as representações presentes para aquela mídia ao longo da
reprodução, sem interrupções perceptíveis. Esta necessidade cria um problema de
sincronismo entre as representações, já que cada uma exigirá uma quantidade diferente
de dados a serem transmitidos por segundo. Para solucionar esta questão,
desenvolveu-se o vídeo segmentado, em que as diversas representações são
fragmentadas em blocos a serem pedidos pelos clientes. O sincronismo é mantido pelos
índices destes fragmentos, devidamente associados a cada representação. Assim, o
cliente pedirá pelo fragmento seguinte de outra representação, caso haja
necessidade/condições de alternância.
13
15
O projeto inicial do servidor proxy já era voltado ao vídeo segmentado, mas não
incluía a funcionalidade de lidar com múltiplas taxas de uma mesma mídia. Além disso,
sua implementação tratava os vídeos de forma genérica, não se utilizando de recursos
fornecidos pelo HDS.
1.4 – Objetivos
Este projeto objetiva, portanto, tornar o servidor proxy capaz de tratar pedidos de
fragmentos segundo o padrão HDS, se utilizando dos metadados fornecidos para
reservar a memória necessária para o cacheamento do vídeo a ser transmitido e
entendendo as múltiplas taxas de uma mesma mídia como associadas a um único vídeo.
O intermédio do servidor proxy na alteração das taxas não deve interromper a
reprodução do vídeo de forma perceptível aos clientes, bem como a obtenção de
informações prévias sobre a mídia transmitida deve atrasar o início da reprodução pelo
mínimo tempo possível.
1.5 – Metodologia
Para entender como se processam os pedidos de fragmentos de vídeo pelo
padrão HDS e quais informações podem ser obtidas na forma de metadados para tornar
o servidor proxy mais eficiente, houve uma etapa inicial de pesquisa para compreensão
do padrão, focada principalmente na leitura da documentação fornecida pela Adobe ©
[1].
Sabe-se que os metadados úteis são enviados ao reprodutor de vídeos através de
um arquivo chamado genericamente de manifest. Parte da pesquisa da primeira etapa
resumiu-se à interpretação das informações contidas neste arquivo de manifest [1].
Paralelamente à primeira etapa, o próprio projeto inicial do servidor proxy teve
de ser entendido, sobretudo a organização de suas unidades de compilação e a
implementação da comunicação cliente-servidor. Assim, foram necessárias pesquisas
sobre as bibliotecas utilizadas, principalmente a Boost [2].
Uma vez compreendidos os métodos como os fragmentos são pedidos no padrão
HDS e a forma como a comunicação se estabelece no proxy, identificaram-se as
mudanças na rotina de pedidos de segmentos que o proxy intermedia, uma vez que o
projeto inicial não se utilizava dos metadados.
Concluindo a implementação deste projeto, diversas estruturas de dados
utilizadas nas classes do projeto original foram modificadas, se tornando compatíveis
com as múltiplas representações que serão transmitidas.
Como última etapa, numerosos testes foram realizados, para verificar se os
metadados estão sendo interpretados corretamente e se a reprodução dos vídeos com
variação de taxas ocorreu sem interrupções.
1.6 – Descrição
O capítulo 1 trata desta introdução.
O capítulo 2 apresenta uma análise do arquivo de manifest associado ao HDS,
explicando sua organização e descrevendo os recursos utilizados para extrair suas
informações.
O capítulo 3 destaca como as informações obtidas pelo arquivo de manifest
alteram o projeto original do servidor proxy.
O capítulo 4 explica como outras ferramentas além do ambiente de programação
foram úteis à conclusão do projeto, destacando os principais problemas encontrados na
implementação das adaptações ao proxy.
O capítulo 5 apresenta resultados e as conclusões do projeto.
O capítulo 6 cita trabalhos futuros associados ao projeto.
Um capítulo de referências finaliza este relatório.
15
Capítulo 2
O Arquivo de Manifest
2.1 – Justificativa para o uso do manifest
Para que a transmissão de um arquivo de vídeo seja bem sucedida, o dispositivo
de reprodução solicita determinadas informações sobre a mídia. Estas podem incluir a
duração do vídeo, o número de segmentos que o compõem, quais idiomas de áudio
estarão disponíveis, entres outras.
Entre as diversas maneiras através das quais estas informações podem ser
pedidas ao servidor, a implementação do HDS optou por agrupá-las num único arquivo,
a ser solicitado antes da reprodução do vídeo. Este arquivo é chamado genericamente de
manifest e possui formato “.f4m”, no caso do HDS.
Assim, todos os denominados metadados – dados relacionados à mídia sem ser a
própria – estão presentes no arquivo de manifest, e a primeira etapa do projeto consistiu
em selecionar quais deles seriam úteis à transmissão do vídeo pelo servidor proxy.
2.2 – Informações importantes do manifest
A primeira demanda do projeto era que o servidor proxy fosse capaz de
armazenar memória antes de os segmentos de vídeo serem pedidos pelo cliente para
qualquer mídia transmitida através do HDS. Para isto, dever-se-iam obter as
informações relevantes do arquivo de manifest, solicitado pelo cliente logo após o
estabelecimento da conexão entre o mesmo e o servidor.
O Anexo A mostra um exemplo de arquivo de manifest. Trata-se de uma
estrutura XML, cuja definição pode ser vista em [3]. Verificou-se que as informações
fundamentais às alterações desejadas estavam contidas no nó bootstrapInfo.
16
18
O conteúdo do nó bootstrapInfo encontra-se codificado no padrão base-64, para
minimizar o tamanho do arquivo de manifest. A decodificação deste conteúdo gera uma
string estruturada conforme especificado na documentação da Adobe © [1]. Nesta string
está a maior parte dos dados necessários ao armazenamento prévio de memória, de tal
forma que a primeira etapa do projeto consistiu em uma rotina para a extração e a leitura
correta dos dados contidos no nó bootstrapInfo. Esta rotina foi implementada no projeto
auxiliar denominado Bootstrap Parser.
Além do nó bootstrapInfo, verificou-se que outras informações importantes
poderiam estar presentes nos nós . Estas não necessariamente serão utilizadas, pois
podem não existir no arquivo de manifest. A documentação da Adobe © [1] especifica
quais atributos integram obrigatoriamente o manifest ou não.
2.3 – Bootstrap Parser
O projeto auxiliar Bootstrap Parser objetiva extrair o conteúdo do nó
bootstrapInfo de um arquivo de manifest, no formato .f4m. A partir da leitura e da
decodificação deste conteúdo, a string estruturada obtida terá seus elementos
discriminados e associados a variáveis-membros de uma classe previamente preparada
para tal, sendo capaz, portanto, de informar as características do vídeo presentes no
arquivo de manifest.
Conforme especificado na documentação do padrão HDS [1], o conteúdo do nó
bootstrapInfo de um arquivo F4M refere-se à chamada bootstrap info box, identificada
pela sigla abst e representada pela string já citada. Esta string é considerada estruturada
porque ela é composta pela concatenação, bit a bit, de diversas informações, de tal
forma que é necessário conhecer a disposição das mesmas para a leitura correta da
string. As informações podem ser entendidas como a sucessão dos seguintes elementos,
na ordem apresentada:
1. o cabeçalho da abst (de 8 a 16 bytes);
2. a versão da box (1 byte);
3. valores reservados para flags (3 bytes);
4. versão da informação de bootstrap (4 bytes);
19
5. identificador de perfil (2 bits);
6. indicador de apresentação ao vivo (1 bit);
7. indicador de atualização (1 bit);
8. bits reservados (4 bits) – os últimos quatro parâmetros, incluindo este, são
representados através de um único caractere (ou seja, um único byte) da string;
9. escala de tempo (4 bytes);
10. instante atual da mídia (8 bytes);
11. offset entre o instante atual da mídia e o código temporal SMPTE (8 bytes);
12. identificador do vídeo (string);
13. número de entradas da tabela de URLs do servidor (1 byte);
14. tabela de URLs do servidor (apenas se o número de entradas não for nulo);
15. número de entradas da tabela de referências para níveis de qualidade da mídia (1
byte);
16. tabela de referências para níveis de qualidade da mídia (apenas se o número de
entradas não for nulo);
17. metadados de direitos autoriais digitais (DRM) (string);
18. metadados genéricos (string);
19. número de entradas na tabela de segmentos (1 byte);
20. tabela de segmentos;
21. número de entradas na tabela de fragmentos (1 byte); e
22. tabela de fragmentos.
Assim sendo, o projeto Bootstrap Parser gera um objeto de uma classe
desenvolvida para armazenar o conteúdo destes 22 parâmetros, oriundo de um nó
bootstrapInfo de um arquivo F4M. Para tanto, desempenha as seguintes tarefas:
leitura de um arquivo de manifest no formato “.f4m”;
extração do conteúdo do nó bootstrapInfo, com a subsequente decodificação
deste conteúdo, segundo o código base-64; e
parsing1 do conteúdo decodificado através dos membros da classe abst.
1Parsing é a ação de identificar determinadas informações e associá-las a estruturas correspondentes e
conhecidas.
20
Entre todos os dados lidos da estrutura da abst, as informações essenciais ao
projeto do servidor proxy encontram-se na tabela de segmentos, identificada por asrt, e
na tabela de fragmentos, identificada por afrt.
A Segment Run Table, ou asrt, é composta por parâmetros ordenados, a saber:
1. o cabeçalho da asrt (de 8 a 16 bytes);
2. a versão da asrt (1 byte);
3. valores reservados para flags que caracterizam a tabela (3 bytes);
4. o número de modificadores para as URLs dos Segmentos relativos aos diferentes
níveis de qualidade da mídia (1 byte);
5. modificadores para as URLs dos Segmentos relativos aos diferentes níveis de
qualidade da mídia (string);
6. número de elementos na tabela de entradas de Segmentos reproduzíveis (4
bytes); e
7. tabela de entradas de Segmentos reproduzíveis – Segment Run Entry Table (8
bytes).
A tabela de entradas de Segmentos reproduzíveis lista informações inerentes aos
Segmentos e pode ser decomposta nos seguintes campos, apresentados na ordem em
que aparecem:
1. índice do primeiro Segmento (4 bytes); e
2. número de Fragmentos por Segmento (4 bytes).
Como será explicado na próxima seção, nem todos os índices dos Segmentos
reproduzíveis aparecerão na abst, devido à minimização do tamanho do arquivo de
manifest. Assim sendo, o índice do primeiro Segmento especifica o primeiro Segmento
da possível sequência de Segmentos de mesma duração que será apresentada na asrt.
O número de Fragmentos por Segmento, por sua vez, indica o número de
Fragmentos contidos no Segmento ao qual este elemento da tabela de entradas de
Segmentos reproduzíveis faz referência.
Já a Fragment Run Table, ou afrt, é constituída pelos seguintes elementos, na
respectiva ordem:
21
1. cabeçalho da afrt (de 8 a 16 bytes);
2. versão da afrt (1 byte);
3. valores reservados para flags que identificam a tabela (3 bytes);
4. escala de tempo que servirá para todos os parâmetros temporais da afrt (4 bytes);
5. número de entradas da tabela de modificadores das URLs dos Segmentos
relativos à qualidade da mídia (1 byte);
6. modificadores das URLs dos Segmentos relativos à qualidade de midia (string);
7. número de elementos da tabela de entradas de Fragmentos reproduzíveis (4
bytes); e
8. tabela de entradas de Fragmentos reproduzíveis (de 16 a 17 bytes).
A tabela de entradas de Fragmentos reproduzíveis lista as informações de cada
Fragmentos e é composta pelos seguintes campos, na respectiva ordem:
1. índice do primeiro Fragmento (4 bytes);
2. marcador de instante de tempo do primeiro Fragmento (8 bytes);
3. duração do Fragmento (4 bytes); e
4. indicador de descontinuidade (de 0 a 1 byte).
Tal como o índice do primeiro Segmento explicado acima, o índice do primeiro
Fragmento indica o primeiro Fragmento de uma eventual sequência de Fragmentos de
mesma duração. O marcador de instante de tempo do primeiro Fragmento representa o
instante inicial do mesmo.
A duração do Fragmento é autoexplicativa. Caso este elemento da tabela
represente um conjunto de Fragmentos, a mesma duração será atribuída a todos os
elementos deste conjunto.
O indicador de descontinuidade só estará presente caso a duração seja nula.
Neste caso, ele ocupará um único byte da tabela e este Fragmento não será pedido pelo
cliente. Esta descontinuidade pode ser na numeração dos Fragmentos, nos marcadores
de instante de tempo e ou em ambos. Um Fragmento com indicador de descontinuidade
igual a 0 tipicamente encerra a sequência de Fragmentos da mídia, uma vez que este
indicador é interpretado como fim da reprodução.
22
Os segmentos e os fragmentos são as estruturas básicas de seccionamento dos
vídeos no padrão HDS. A organização interna dos vídeos segmentados segundo o HDS
será detalhada na próxima seção.
2.4 – Segmentação do vídeo em HDS
O vídeo segmentado segundo o padrão HDS é dividido em Segmentos, os quais,
por sua vez, se seccionam em Fragmentos. A documentação não especifica qual seria a
utilidade de um vídeo ter mais de um Segmento, e todos os exemplos encontrados só
possuíam um Segmento. Apesar disto, o programa está preparado para armazenar em
cache vídeos com múltiplos Segmentos.
Os Fragmentos são as unidades básicas do vídeo, que efetivamente armazenam o
conteúdo a ser assistido. O cliente deverá pedir pelos Fragmentos através de sua URI,
que sempre seguirá o padrão “<diretorio-associado-ao-servidor|Seg#-Frag#>”2, em que
o símbolo “#” referir-se-á ao índice do Segmento ou do Fragmento, quando acompanhar
o termo “Seg” ou “Frag”, respectivamente.
Os índices dos Fragmentos estão dispostos na afrt do arquivo de manifest. No
entanto, duas peculiaridades devem ser observadas:
Fragmentos consecutivos com a mesma duração; e
Fragmentos marcados como indicativos de descontinuidade.
Para minimizar o tamanho do arquivo de manifest, Fragmentos consecutivos
com a mesma duração não são representados: apenas o primeiro deles está presente
entre os metadados. Por exemplo, se os Fragmentos de índices 3, 4 e 5 possuírem a
mesma duração, mas o Fragmento 6, não, na afrt estarão presentes os índices 3 e 6
(estes números corresponderão ao campo “índice do primeiro Fragmento” na tabela de
entradas de Fragmentos reproduzíveis). Subentende-se que, caso índices consecutivos
não difiram de uma unidade, os índices ausentes referem-se a Fragmentos que possuem
a mesma duração que aquele cujo índice é o primeiro dos consecutivos. No exemplo, os
Fragmentos 4 e 5 possuem a mesma duração que o 3, daí eles estarem ausentes. A
2O símbolo “|” não está presente nas URIs dos Fragmentos, existindo apenas para separar o diretório dos
Fragmentos da expressão “Seg”.
23
interpretação do conteúdo da afrt exige que se conheça esta particularidade. O mesmo
vale para os Segmentos da asrt. A Tabela 2.1 ilustra uma tabela de Fragmentos com 10
deles, distribuídos de forma correspondente ao exemplo dado.
Entrada 1
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
1 0 5 ausente
Entrada 2
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
2 5 3 ausente
Entrada 3
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
3 8 5 ausente
Entrada 4
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
6 23 2 ausente
Entrada 5
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
9 29 5 ausente
Entrada 6
Índice do 1º Fragmento Instante inicial Duração Indicador de descontinuidade
0 0 0 0
Tabela 2.1: exemplo de tabela de entradas de Fragmentos. Nota-se que se trata de uma tabela de nove
Fragmentos, sendo o último apenas o indicador de término do vídeo.
Os Fragmentos marcados com o indicador de descontinuidade possuem duração
nula e, portanto, não devem ser pedidos. O motivo pelo qual estes Fragmentos podem
estar presentes varia de acordo com a mídia. No entanto, seus índices estão contidos na
afrt, mas estes Fragmentos devem ser identificados para que não sejam solicitados pelo
cliente; também não lhes deverá ser reservado, pois, memória em cache. Como já
citado, o último Fragmento de uma mídia, em geral, possui indicador de
descontinuidade igual a 0, servindo para informar o fim da apresentação.
Discutida neste capítulo a importância do uso das informações obtidas do
arquivo de manifest, o próximo capítulo descreverá quais mudanças o projeto original
teve de sofrer para se adaptar à inclusão da leitura do manifest.
24
Capítulo 3
Modificações no Servidor Proxy
3.1 – Classes e estruturas auxiliares
O projeto Bootstrap Parser, apresentado no capítulo anterior, pode ser
considerado um projeto auxiliar ao do servidor proxy. Contudo, é um projeto externo,
cujos métodos e classes não são utilizados nos arquivos originalmente componentes do
servidor. Esta seção apresentará as classes criadas como internas ao projeto original,
bem como estruturas desenvolvidas como parte das alterações que são detalhadas neste
relatório.
Como será comentado posteriormente, a interpretação do conteúdo do arquivo
de manifest é realizada na unidade de compilação proxy-conn. Uma vez obtido todo este
conteúdo, uma string é passada como argumento de um objeto da classe f4mParser, que
intitula o código-fonte totalmente desenvolvido como parte das alterações previstas.
Para obter o conteúdo do arquivo de manifest, foi definida uma estrutura
denominada manifestInfo, utilizada internamente à classe citada para copiar as
informações obtidas de modo inteligível ao projeto, mais especificamente à estrutura de
cache, como será explicado.
3.1.1 – A unidade de compilação f4mParser
Com o objetivo de encapsular todas as rotinas referentes à leitura e à extração
das informações importantes ao funcionamento do servidor proxy oriundas do arquivo
de manifest, foi desenvolvida a unidade de compilação f4mParser, uma das principais
alterações descritas neste relatório.
25
A Fig. 3.1 mostra como os métodos da unidade de compilação f4mParser se
relacionam. Esta unidade é composta por um método público chamado
getHubInformation, que preenche o conteúdo de uma variável ManifestInfo a partir das
informações lidas do arquivo de manifest, cujo conteúdo, previamente armazenado em
uma string, é passado ao objeto f4mParser. Este conteúdo é atribuído a um membro
privado m_manifest.
Fig. 3.1: relação de dependência entre os métodos da classe f4mParser.
O método findCommonSection aparece isolado por ser um método auxiliar do findVideoKey.
O método público utiliza rotinas encapsuladas em diversos métodos privados, a
saber:
findBootstrapInfo, para obter todo o conteúdo dos nós bootstrap que podem
estar presentes no arquivo de manifest através de um vetor de elementos string,
um para cada nó bootstrap contido no arquivo;
findMediaInformation, que extrai o conteúdo dos atributos bitrate e url de todos
os nós media presentes no arquivo de manifest, através de um vetor de números
reais do tipo double e de um vetor de elementos string, respectivamente;
findVideoKey, que identifica a parcela comum a todas as URLs associadas ao
vídeo, destacando-a como chave para o mesmo e gerando um vetor com
identificadores das diversas representações nas quais o vídeo estiver
apresentado;
26
fillNumberFragments, responsável pelo cálculo do número de Fragmentos
válidos nos quais cada Segmento está dividido, ou seja, o número de Fragmentos
que efetivamente serão pedidos pelo cliente para a reprodução do vídeo;
findDuration, que obtém a duração da mídia;
findCommonSection, utilizado na rotina do método findVideoKey; e
writeVFF, apenas para testes.
A informação da taxa de bits em que o vídeo é reproduzido, ou seja, o bit rate, é
necessária para a estimativa do tamanho em bytes do vídeo, uma vez que o produto
dessa taxa pela duração do vídeo resulta no tamanho do mesmo. Desta forma, faz-se
necessária a obtenção desta informação, através do método findMediaInformation.
Outra utilidade do mesmo método é a extração das chamadas media URLs,
referentes a cada uma das representações cujas características estão descritas no arquivo
de manifest. Estas URLs servirão de base para os identificadores das representações.
Detalhando o padrão apresentado anteriormente, cada URL de um Fragmento
pode ser entendida através do seguinte padrão:
<[domínio]/[chave do vídeo][chave da representação][Seg#-Frag#]>
O método findVideoKey analisa todas estas URLs para identificar uma parcela
das mesmas que lhes seja comum, excluindo o domínio do servidor, o que é a chamada
chave do vídeo, ou, em Inglês, video key. Analisando apenas a string das URLs, podem-
se identificar também parcelas comuns a cada representação individualmente, o que
gerará, no mesmo método, um vetor de chaves de representação, ou representation keys.
Quando só houver uma representação, as chaves do vídeo e da representação
coincidirão.
Para obter a chave do vídeo, o método findVideoKey faz uso do método auxiliar
findCommonSection, que compara iterativamente os elementos de vetor de strings
fornecido caractere a caractere, retornando em uma string com a parcela comum a todas
que compõem o vetor de entrada.
27
Explicando detalhadamente o método fillNumberFragments, o número total de
Fragmentos pode ser obtido diretamente pelas informações de bootstrap. Contudo,
alguns destes Fragmentos não serão pedidos pelo cliente por serem meros indicadores
de descontinuidade dentro do vídeo, possuindo, portanto, duração nula. Embora a
função destes Fragmentos varie de mídia para mídia e fuja ao escopo deste projeto, seus
índices devem ser identificados e excluídos da lista de Fragmentos válidos.
O método findDuration tenta preferencialmente obter a duração da mídia através
do nó duration, que poderá estar presente no arquivo de manifest. Caso não esteja, um
método auxiliar do projeto Bootstrap Parser obtém a duração a partir da tabela de
Fragmentos, que contém informações sobre a duração individual de cada Fragmento,
conforme descrito na Seção 2.3.
Por fim, o método writeVFF escreve a lista de Fragmentos válidos em um
arquivo, apenas para testar se esta foi obtida corretamente. Este método seria removido
de uma versão comercial do programa.
3.1.2 – A estrutura manifestInfo
A estrutura manifestInfo estabelece a integração da classe f4mParser ao projeto
do servidor proxy, sendo utilizada em dois contextos semelhantes, conforme detalhado
posteriormente:
obter todas as informações pertinentes do arquivo de manifest em um método da
unidade proxy-conn; e
armazenar estas informações para o processamento interno de criação da cache,
através de métodos das unidades de compilação hub e Mcc.
Como toda estrutura, manifestInfo é composta por um conjunto de membros, a
saber:
28
nFragments, um vetor de números inteiros sem sinal cujos elementos são o
número de Fragmentos de cada representação componente da mídia;
fragmentUrl, um vetor de strings cujos elementos indicam a parcela comum às
URLs de cada representação componente da mídia;
validFragments, um vetor de vetores de números inteiros sem sinal cujos
elementos são listas dos Fragmentos válidos de cada representação componente
da mídia;
duration, um número real que representa a duração, em milissegundos, do vídeo;
vBitrate, um vetor de números reais cujos elementos correspondem à taxa de bits
por segundo de cada representação componente da mídia;
videoPattern, uma string equivalente à parcela comum a todas as URLs dos
Fragmentos da mídia, ou seja, da parcela que caracteriza o vídeo; e
representations, um vetor de strings cujos elementos destacam a parcela das
URLs dos Fragmentos relativos a cada representação componente da mídia.
A Tabela 3.1 ilustra uma estrutura manifestInfo preenchida para uma mídia de
três representações. Nota-se que os membros nFragments, fragmentUrl,
validFragments, vBitrate e representations são vetores de mesmo número de elementos,
o qual é igual, por sua vez, ao número de representações da mídia. Esta característica foi
utilizada ao longo do projeto como método para verificar se todos os membros do
objeto manifestInfo foram preenchidos corretamente.
Além disso, os elementos destes cinco membros são correspondentes. Por
exemplo, o terceiro elemento do membro nFragments será igual ao número de
Fragmentos da terceira representação, assim como o terceiro elemento do membro
vBitrate será o número de bits por segundo da terceira representação.
Analisando o padrão das URLs dos Fragmentos apresentado na subseção
anterior, pode-se considerar que a string videoPattern corresponde à chave do vídeo,
enquanto que o vetor representations contém chaves de representações.
29
Representação 1 Representação 2 Representação 3
nFragments 30 30 30
fragmentUrl /video/rep1 /video/rep2 /video/rep3
validFragments3 23 23 23
duration 600
vBitrate 300 600 900
videoPattern /video/
representations rep1 rep2 rep3
Tabela 3.1: estrutura manifestInfo após obter informações
de uma mídia composta por três representações.
Finalizando as observações sobre a estrutura manifestInfo, espera-se que todos
os elementos do membro nFragments resultem no mesmo número, uma vez que não é
comum representações de um mesmo vídeo apresentarem diferença na quantidade de
Fragmentos. Contudo, este membro se mostrou necessários ao longo dos testes, pois um
dos vídeos reproduzidos apresentava esta peculiaridade.
3.2 – Unidades de compilação modificadas
O projeto Asio Proxy Async era composto originalmente pelas seguintes
unidades de compilação:
base-connection;
cache;
client-connection;
header_handle;
hub;
Mcc;
mem-profiler;
3Na Tabela 3.1, os campos referentes ao membro validFragments correspondem ao número de elementos
de cada vetor associado à respectiva representação indicada pela coluna.
30
metadata-fetcher;
origin-connection;
parseini;
pool;
proxy-conn;
proxy-server;
resolver;
segment;
slot-buffer;
util; e
visualizer.
Cada uma destas unidades corresponde a dois arquivos homônimos:
um código-fonte, de extensão .cpp; e
um arquivo de cabeçalho, de extensão .hpp.
Além das unidades citadas, os seguintes arquivos merecem destaque:
a rotina de execução do programa gerado a partir da compilação do projeto,
armazenada no arquivo main.cpp;
o arquivo de cabeçalho que concentra definições comuns a diversas unidades,
common.h; e
o arquivo de dependências, essencial para a organização do projeto, denominado
Makefile.
31
Os itens em negrito fazem parte do escopo deste relatório e receberão, a seguir,
subseções particulares que detalharão como o entendimento de suas rotinas ou as
alterações das unidades de compilação às quais eles se referem estão associados a este
Projeto de Graduação. A Fig. 3.2 mostra como as unidades de compilação se relacionam
durante a execução do servidor proxy.
Fig. 3.2: relação sequencial entre as unidades de compilação do projeto Asio Proxy Async. [12]
Cabe ressaltar, ainda, que as unidades em destaque lidam com etapas diferentes
do processo, que se inicia com a interpretação dos pedidos do cliente e que se encerra
com o acesso à cache para obter os Fragmentos de vídeo. Estas etapas serão definidas a
cada subseção.
3.2.1 – proxy-conn
A unidade de compilação proxy-conn é responsável por estabelecer a conexão
entre o cliente e o servidor, reunindo as rotinas que iniciam o ciclo de vida do servidor
proxy em execução. Desta maneira, lida com a etapa inicial, interpretando os pedidos do
cliente e as respostas do servidor, sendo exclusivamente voltado à conexão.
32
Nesta unidade, estão definidos os métodos da classe Connection, através da qual
são desempenhadas as seguintes tarefas:
interpretação dos cabeçalhos dos pedidos feitos pelo cliente e das respostas
enviadas pelo servidor, a fim de identificar que tipo de dado foi solicitado ou
será recebido;
a partir destes cabeçalhos, análise da URL correspondente ao endereço da
informação transmitida;
determinação do estado do servidor proxy em relação à transmissão e à
disponibilidade do vídeo a ser reproduzido;
obtenção do arquivo de manifest, para posterior preparação da cache para obter
os próximos Fragmentos de mídia a serem exibidos; e
solicitação do registro da conexão, após as devidas validações.
As principais modificações realizadas nesta unidade foram:
o registro da conexão passa a ocorrer posteriormente ao pedido do primeiro
Fragmento de vídeo pelo cliente, ao invés de no construtor da classe Connection;
e
o conteúdo do arquivo de manifest é obtido de forma assíncrona, e apenas após a
leitura do mesmo os pedidos de Fragmentos de vídeo serão aceitos.
As duas mudanças foram necessárias para tornar o programa genérico, capaz de
interpretar pedidos de quaisquer vídeos no padrão HDS. Anteriormente às modificações,
as URLs dos Fragmentos deveriam ser inseridas no código de maneira hard-coded, e os
pedidos por arquivo de manifest eram ignorados. Agora, o registro da conexão só é
realizado após a validação das informações obtidas do arquivo de manifest. Da mesma
forma, o servidor proxy pode solicitar os Fragmentos de vídeo posteriores àquele pedido
pelo cliente, para que a cache os prepare, o que só é possível através da análise do
arquivo de manifest. As URLs dos Fragmentos também são lidas do último.
33
Por fim, o método de registro da conexão faz parte da rotina da unidade proxy-
conn. Contudo, sua implementação pertence à unidade hub, comentada a seguir.
3.2.2 – hub
Enquanto a unidade de compilação proxy-conn contém rotinas exclusivamente
relacionadas com a comunicação entre o cliente e o servidor, a unidade hub implementa
a classe Hub, cujos métodos associam os dados pedidos pelo cliente com as
informações armazenadas na ou fornecidas pela cache.
A única maneira de métodos de outras unidades acessarem a cache é através de
métodos implementados na unidade hub, a qual, por sua vez, só acessa a cache a partir
de métodos da unidade Mcc, detalhada na próxima subseção.
As modificações realizadas aos métodos da unidade hub foram as seguintes:
os argumentos do método Hub::translateIndex recebem um índice de segmento
e duas strings, relativas aos identificadores do vídeo e da representação,
conforme será explicado posteriormente;
foi implementado o método Hub::insertVideo, que, através de um argumento
ManifestInfo, fornece o identificador do vídeo e os dados obtidos do arquivo de
manifest a um objeto mcc, apresentado na próxima subseção; e
foi implementado o método Hub::findUrl, utilizado na unidade proxy-conn para
identificar se a URL passada como argumento corresponde à de um Fragmento
de vídeo válido ou não.
34
3.2.3 – Mcc
A unidade de compilação Mcc implementa a classe mcc, a qual fornece métodos
de acesso aos membros da classe cache. Conforme comentado, os métodos da classe
Hub só podem obter informações da cache através dos métodos da classe mcc. Por este
motivo, a maioria dos métodos da classe Hub possui um homônimo na classe mcc.
As modificações realizadas na unidade Mcc podem ser incluídas entre as mais
importantes para este projeto de graduação, uma vez elas permitiram ao servidor proxy
lidar com pedidos de múltiplos vídeos simultâneos. Isto foi possível através da
implementação de uma matriz de caches, simbolizada pelo objeto-membro cacheMap,
um mapa de identificadores de vídeo para ponteiros para objetos da classe cache. Sua
declaração correspondente à seguinte linha de código:
std::map<std::string, CachePtr> cacheMap;
Assim, cada instância de um objeto cache representa uma mídia cujos
Fragmentos foram pedidos pelo cliente, sendo esta mídia identificada através de uma
chave de vídeo.
A maior parte das mudanças ocorridas diz respeito à substituição do acesso a um
único ponteiro para cache pelo acesso a um ponteiro específico, a partir da string
identificadora, dentro de um mapa de ponteiros. Além destas, é importante notar que o
Fragmento de vídeo passou a ser identificado através de uma tríade de elementos,
conforme já comentado e, agora, ilustrado na Fig. 3.3:
um identificador de vídeo, chamado video key e implementado como uma string;
um identificador de representação, chamado representation key e implementado
como uma string; e
um índice de Fragmento, válido para cada representação, chamado segment
index e implementado como um número inteiro.
35
Fig. 3.3: tríade identificadora dos Fragmentos de vídeo para
uma mídia de duas representações com três Fragmentos cada.
Assim sendo, os métodos que sofreram as alterações mais notáveis foram:
Mcc::translateIndex, que obtém a URL de um Fragmento, fornecida a tríade
identificadora – e que anteriormente só necessitava de um índice de Fragmento;
Mcc::translateUrl, que, a partir de uma estrutura ParsedUrl, obtém a tríade
identificadora, retornada através de uma estrutura TranslatedUrl;
Mcc::fetchSegmentMetadata, que passou a gerar um vetor de objetos
MetadataFetcher em lugar de uma única instância dos mesmos; e
Mcc::parseUrl, cuja modificação corresponde às alterações da própria estrutura
de retorno, ParsedUrl, com a inclusão de um novo método auxiliar,
searchSegRawUrl.
A estrutura TranslatedUrl foi criada para reunir a tríade identificadora dos
Fragmentos, podendo ser entendida como uma forma condensada da estrutura
ParsedUrl, que já existia no projeto original. Esta última, por sua vez, distingue os
elementos formadores de uma URL, como será comentado na subseção relativa ao
arquivo de cabeçalho common.h.
Entre os métodos desenvolvidos por este projeto, estão:
36
Mcc::insertVideo, que é chamado através do homônimo da classe Hub e que
instancia um novo ponteiro para cache, a partir de uma estrutura ManifestInfo, e
registra efetivamente a conexão em seguida. Também é responsável por inserir
as informações de protocolo, de domínio e de diretório dos Fragmentos na
cache, por adicionar a nova instância de cache ao objeto-membro cacheMap e
por chamar o método Mcc::fetchSegmentMetadata;
Mcc::findUrl, chamado exclusivamente através de seu homônimo da classe Hub,
verificando se a URL passada como parâmetro de entrada está presente na cache
e correspondente à URL de um Fragmento de vídeo válido; e
Mcc::searchSegRawUrl, que, através de expressões regulares, identifica as
chaves do vídeo e da representação da URL contida em uma estrutura
ParsedUrl passada como parâmetro de entrada.
3.2.4 – cache
Na unidade de compilação cache, alterações igualmente importantes às da
unidade Mcc foram realizadas, pois, através delas, o servidor proxy tornou-se capaz de
lidar com vídeos segmentados em múltiplas taxas, ou múltiplas representações,
entendendo as várias representações de uma mesma mídia como uma única mídia.
A classe cache, implementada nesta unidade, dá acesso ao vetor de objetos
segment, que simbolizam os Fragmentos do vídeo. Para permitir a interpretação das
múltiplas taxas de um mesmo vídeo como distintas foi necessária a substituição do vetor
de Fragmentos por uma matriz de vetor de Fragmentos na qual cada elemento é
identificado por uma chave de representação. Esta matriz é objeto-membro
mRepresentations, declarado através da seguinte linha de código:
std::map<std::string, std::vector<segment, PooledAllocator<Block> > >
mRepresentations4;
4 Os vetores de objetos segment contidos em mRepresentations possuem um alocador definido na classe
cache no projeto original. Os motivos pelos quais este alocador foi escolhido fogem ao escopo deste
projeto.
37
Além disso, é importante compreender que a classe cache é responsável pela
obtenção dos Fragmentos presentes no servidor de origem, conforme os mesmos são
pedidos pelo cliente. Quando o cliente realiza o pedido de um Fragmento, a classe
cache possui funcionalidade para armazenar os quatro Fragmentos seguintes,
gerenciando, assim, um buffer de Fragmentos para evitar latências na reprodução do
vídeo. As informações obtidas no arquivo de manifest auxiliam a cache a desempenhar
esta tarefa, sobretudo no momento em que o cliente pedir vídeos em outras taxas.
Tal qual na classe mcc, a maior parte das alterações da classe cache refere-se à
substituição do acesso a um único vetor de objetos segment pelo acesso a um vetor
identificador através de uma string, dentro de uma mapa de vetores. Além destas
modificações, devem-se destacar as seguintes mudanças:
o construtor da classe cache, que passou a receber uma estrutura ManifestInfo
como parâmetro de entrada, através da qual os objetos-membro
mRepresentations e m_mSuffix – que associa o sufixo das URLs de cada
Fragmento ao seu índice – são preenchidos; e
os métodos cache::increaseUserCount e cache::decreaseUserCount, que
receberam versões sobrecarregadas, podendo alterar a prioridade de um
Fragmento em todas as representações em que ele se fizer presente (caso o
parâmetro de entrada seja apenas seu índice) ou em uma representação
específica (caso o parâmetro de entrada seja sua tríade identificadora).
Foram implementados, ainda, os seguintes métodos:
métodos de acesso e de configuração para os objetos-membro m_protocol,
m_host e m_path, que correspondem, respectivamente, ao protocolo, ao domínio
e ao diretório obtidos das URLs do vídeo associado à cache e cuja declaração
está entre as modificações realizadas por este projeto final;
38
cache::searchSegment, que é usado na obtenção do índice dos Fragmentos, a
partir de um sufixo de Fragmento como entrada, na classe mcc, acessando o
objeto-membro m_mSuffix para tal;
cache::getSegmentSuffix, que é utilizado, na classe mcc, para obter o sufixo de
um Fragmento através da tríade identificadora, fornecida como uma estrutura
TranslatedUrl de entrada.
3.2.5 – segment
A unidade de compilação segment implementa a classe segment, a qual, por sua
vez, representa um fragmento genérico de vídeo, não necessariamente atrelado a
nenhum padrão. A única modificação notável pertencente ao escopo deste projeto foi a
declaração do objeto-membro, juntamente a seus métodos de acesso e de configuração,
m_suffix, uma string que contém o sufixo do Fragmento associado à instância da classe
segment. Cabe ressaltar que o uso deste objeto-membro refere-se exclusivamente ao
padrão HDS.
3.2.6 – metadata-fetcher
A unidade de compilação metadata-fetcher pode ser considerada auxiliar ao
projeto, da mesma forma que a unidade f4mParser. Seu código-fonte implementa a
classe MetadataFetcher, responsável por adiantar os pedidos dos cabeçalhos de todos os
Fragmentos da mídia a ser transmitida. Através destes cabeçalhos, pode-se obter o
tamanho em bytes de cada um dos Fragmentos e, assim, o servidor proxy pode solicitar
a alocação de memória mais adequada possível às necessidades da transmissão do
vídeo.
Todas as rotinas envolvendo a classe MetadataFetcher se iniciam com a
chamada do método Mcc::fetchSegmentMetadata, comentado na subseção 3.2.3. Como
os cabeçalhos pedidos passaram a ser referentes a múltiplas representações, elementos
singulares se tornariam vetoriais; escolheram-se, pois, modificações externas à unidade
39
metadata-fetcher, devido à complexidade das rotinas da mesma. Assim, ao longo da
execução do programa, são criadas múltiplas instâncias de objetos MetadataFetcher,
uma para cada representação da mídia.
Para garantir o assincronismo, a classe MetadataFetcher recebe a chave da
representação de cujos Fragmentos os cabeçalhos serão pedidos. Esta chave será
passada ao objeto cache associado à mídia através de um handler, relacionando o vetor
de tamanhos de Fragmentos à sua respectiva representação.
3.2.7 – common.h
O arquivo de cabeçalho common.h contém definições comuns a todas as
unidades de compilação componentes do projeto Asio Proxy Async. Neste arquivo está a
definição da estrutura ManifestInfo, desenvolvida como uma das modificações
realizadas neste projeto final. Além disso, a estrutura ParsedUrl foi alterada e, a partir
dela, a nova estrutura TranslatedUrl foi definida. Esta última possui os seguintes
membros:
keyVideo, uma string referente ao identificador do vídeo;
keyRepresentation, uma string referente ao identificador da representação; e
segIndex, um número inteiro referente ao índice do Fragmento.
Como já comentado, a estrutura TranslatedUrl é considerada uma tríade
identificadora dos Fragmentos, pois, através dela, qualquer Fragmento válido
armazenado em cache pode ser obtido.
A tríade identificadora é gerada a partir das URLs dos Fragmentos. Estas são
compostas por elementos distinguíveis e comuns a qualquer URL de Fragmento de
vídeos no padrão HDS. Estes elementos possuem como correspondentes os membros da
estrutura ParsedUrl, todos strings, a saber:
40
rawUrl, a URL completa do pedido;
protocol, o protocolo da URL, que em geral será “http://”;
domain, parcela referente ao servidor de origem do vídeo;
port, identificador da porta de comunicação entre o cliente e o servidor;
document, URL completa, excluídos os três elementos anteriores;
path, equivalente ao document sem os identificadores de vídeo e de
representação, ou seja, é a parcela da URL que não identifica nenhum elemento
específico, indicando apenas o diretório em que os Fragmentos estão
armazenados no servidor de origem;
keyVideo, identificador do vídeo; e
keyRepresentation, identificador da representação.
Os membros keyVideo e keyRepresentation foram adicionados neste projeto
final.
Por exemplo, se duas URLs de uma mídia a ser transmitida são:
1. http://10.10.10.233/video/teste/video-de-teste3600Seg1-Frag1 e
2. http://10.10.10.233/video/teste/video-de-teste7200Seg1-Frag3,
uma estrutura ParsedUrl teria como membros, para o primeiro Fragmento:
rawUrl: http://10.10.10.233/video/teste/video-de-teste3600Seg1-Frag1;
protocol: http://;
domain: 10.10.10.233/;
port: 8080 (padrão, uma vez que outra não está presente na URL);
document: video/teste/video-de-teste3600Seg1-Frag1;
path: video/teste/;
41
keyVideo: video-de-teste; e
keyRepresentation: 3600.
Já para o segundo Fragmento:
rawUrl: http://10.10.10.233/video/teste/video-de-teste7200Seg1-Frag3;
protocol: http://;
domain: 10.10.10.233/;
port: 8080 (padrão, uma vez que outra não está presente na URL);
document: video/teste/video-de-teste7200Seg1-Frag3;
path: video/teste/;
keyVideo: video-de-teste; e
keyRepresentation: 7200.
Conclui-se, assim, que ambas as URLs referem-se a Fragmentos de um mesmo
vídeo, porém de distintas representações. Para os respectivos Fragmentos, uma estrutura
TranslatedUrl seria preenchida a seguinte forma:
keyVideo: video-de-teste;
keyRepresentation: 3600; e
segIndex: 1, para o primeiro Fragmento.
keyVideo: video-de-teste;
keyRepresentation: 7200; e
segIndex: 3, para o segundo Fragmento.
42
3.2.8 – Arquivo de dependências, Makefile
Para agilizar a compilação dos códigos-fonte e facilitar na referência às
dependências do projeto, utiliza-se um arquivo denominado Makefile para a compilação
e a link-edição necessárias à obtenção do arquivo executável do servidor proxy. Neste
arquivo, estão presentes os nomes de todos os códigos-fonte equivalentes às unidades de
compilação citadas, além de referências às bibliotecas do boost.
A única modificação realizada por este projeto final foi a inclusão dos códigos-
fonte do projeto auxiliar Bootstrap Parser, no diretório bs-parser.
3.3 – Servidor proxy em execução
Esta derradeira seção explicará sucintamente o funcionamento do servidor
proxy, com ênfase maior às modificações abordadas por este projeto de graduação.
Após a execução do aplicativo correspondente ao servidor proxy, estabelece-se
uma conexão entre o mesmo e o cliente. Esta conexão consiste na espera pelo servidor
de pedidos do cliente.
Como os testes são realizados localmente, o cliente é um navegador Web que
solicita acesso a um reprodutor de vídeos, armazenado e previamente configurado no
servidor, e tanto este quanto a máquina a partir da qual o navegador é executado
pertencem ao mesmo laboratório.
Os primeiros pedidos são de componentes do reprodutor, em geral desenvolvido
em JavaScript. Embora o servidor proxy lide com estes pedidos, não utiliza a cache para
tal ação.
Em seguida, comandada a execução do vídeo, o cliente pede o arquivo de
manifest, sendo o mesmo lido de forma assíncrona pelo servidor como parte da rotina da
classe Connection. Nesta etapa, ocorrem as seguintes tarefas, ilustradas pela Fig. 3.4:
43
1. inicialização de um objeto f4mParser, com a passagem do conteúdo do arquivo
de manifest através de uma string;
2. chamada do método insertVideo a partir do objeto-membro hub_ da classe
Connection, o qual consiste em um ponteiro para um objeto da classe Hub;
3. na classe Hub, o método insertVideo repassa a informação extraída do manifest
ao método homônimo da classe Mcc;
4. o método insertVideo da classe Mcc se responsabiliza pela inicialização do
ponteiro para o objeto cache associado ao vídeo que está sendo pedido pelo
cliente. Uma vez inseridas as informações referentes às representações
componentes do vídeo, o ponteiro para cache é inserido no mapa de ponteiros
para cache – o objeto-membro cacheMap da classe Mcc;
5. o método fetchSegmentMetadata também é chamado a partir do método
Mcc::insertVideo, para que as rotinas da classe metadata-fetcher possam obter
os tamanhos, em bytes, de todos os Fragmentos que constituem o vídeo em
questão;
6. após inicializar todos os objetos Segment referentes a uma dada representação, o
vetor dos mesmos é inserido no mapa de representações da cache, que associa a
chave da representação ao vetor de objetos Segment e que instanciado como o
objeto-membro mRepresentations, da classe cache; e
7. os tamanhos dos Fragmentos são passados aos vetores de objetos Segment de
forma assíncrona, através de um handler específico definido na classe cache.
Cada um dos objetos Segment passa, então, a armazenar a informação do
tamanho do Fragmento a ele associado.
No momento em que a leitura do manifest é finalizada, a conexão com o cliente
já se torna disponível novamente, para que os pedidos de Fragmentos de vídeo se
iniciem. Esta disponibilidade é implementada através da chamada do método
Connection::start, que reinicia o ciclo de vida do servidor proxy.
Uma vez feito um pedido de Fragmento de vídeo pelo cliente, a sequência de
métodos da classe Connection ilustrado na Fig. 3.5 se inicia, o mesmo que se estabelece
quando o cliente pede pelo arquivo de manifest. A diferença está na chamada do método
44
Hub::updateSlotBuffer, que só ocorre caso seja identificada a URL de um Fragmento de
mídia.
Fig. 3.4: primeiro ciclo de execução do servidor proxy, quando o cliente faz o pedido pelo manifest.
Através deste último método, os recursos da cache são acessados, criando-se
uma cadeia de slots, que pode ser entendida como uma sequência de quatro Fragmentos
posteriores ao que está sendo pedido pelo cliente. O conteúdo destes quatro Fragmentos
é armazenado em memória, de forma a garantir a transmissão do vídeo sem interrupções
para o cliente.
Conforme a reprodução do vídeo continua, a cada Fragmento pedido pelo
cliente, um novo Fragmento é adicionado ao fim da cadeia de slots, e o Fragmento
assistido pelo cliente, que se localizava no início da cadeia, perde prioridade, sendo seu
conteúdo removido da memória conforme a necessidade.
45
Fig. 3.5: ciclo de métodos para a manutenção da conexão pela
classe Connection, conforme os pedidos pelos Fragmentos de vídeo se sucedem.
O ciclo da Fig. 3.5 se repete até o fim da reprodução da mídia ou até a
interrupção da reprodução pelo cliente. Após um destes eventos, o servidor proxy
permanece ativo, à espera de um novo pedido do cliente.
Em relação à implementação deste projeto de graduação, os capítulos 2 e 3 já
apresentaram todas as tarefas desempenhadas. O próximo capítulo descreverá as
ferramentas auxiliares que se utilizaram para o estabelecimento da metodologia e para a
resolução dos problemas encontradas ao longo da implementação do projeto.
46
Capítulo 4
Ferramentas Auxiliares
Seja para entender melhor o problema proposto, seja para se obter mais
informações durante os testes de execução, aplicativos auxiliares foram utilizados para
desenvolver este projeto final. Estes aplicativos podem ser categorizados da seguinte
forma:
ferramentas para auxiliar na leitura do arquivo de manifest;
um aplicativo para visualização do tráfego entre o cliente e o servidor,
nomeadamente Wireshark;
um sistema de controle de versão, para propiciar o ambiente de desenvolvimento
necessário à implementação do servidor proxy, nomeadamente Git; e
uma ferramenta para depuração, ocorridas falhas de segmentação.
Estas categorias serão detalhadas nas próximas seções.
4.1 – Ferramentas para leitura do manifest
O arquivo de manifest, conforme apresentado no capítulo 2, é uma estrutura
XML contida em um arquivo no formato “.f4m”. Desta forma, seu conteúdo pode ser
entendido com uma cadeia de elementos chave-valor ocasionalmente apresentando
atributos adicionais.
Através da chamada Property Tree, componente do conjunto de bibliotecas do
Boost, a busca pelo nó bootstrapInfo, dado o arquivo de manifest, é implementada em
uma única linha de código. O conteúdo lido encontra-se codificado conforme o código
base-64.
47
Para a decodificação inserida na rotina dos métodos do projeto Bootstrap
Parser, utilizou-se a função base64_decode, implementada a unidade de compilação
presente em [4]. Contudo, para visualizar o conteúdo do nó bootstrapInfo e identificar
quais de seus elementos – enumerados no Capítulo 2 – seriam úteis para as
modificações desejadas ao projeto Asio Proxy Async, a string codificada foi inserida em
um decodificador web, na página indicada em [5], que resulta em um arquivo binário
composto pela string decodificada.
O leitor de arquivos GHex, aplicativo presente no Linux Ubuntu ©, é
responsável por revelar o conteúdo deste arquivo de saída, byte a byte, e os valores
exibidos podem ser comparados com os elementos identificados como pertencentes à
informação de bootstrap. A Fig. 4.1 ilustra o leitor, após a abertura de um arquivo
binário.
Fig. 4.1: Interface do Ghex, após a abertura de um arquivo binário gerado a partir do conteúdo de um nó
de bootstrap pertence a um arquivo de manifest. Na interface superior esquerda, os bytes estão dispostos,
agrupados como dois pares de hexadecimais. À direita, estão os caracteres imprimíveis.
4.2 – Wireshark
A função primordial de um servidor proxy é garantir a comunicação entre o
cliente e o servidor de origem. No caso do servidor proxy implementado no projeto Asio
Proxy Async, esta comunicação é especializada na transmissão de vídeos por streaming.
48
A cada etapa da implementação das alterações ao projeto original, dever-se-ia
verificar se a função básica do servidor proxy estava sendo desempenhada com sucesso.
Por esta razão, houve a necessidade de recorrer a um visualizador de tráfego da rede. O
escolhido foi o Wireshark [6]. A Fig. 4.2 mostra o aplicativo aberto.
Categorizado formalmente como network protocol analyzer – analisador de
protocolo de rede –, o Wireshark exibe os pacotes que foram transmitidos pela rede a
qual ele tem acesso, no intervalo de tempo determinado pelo usuário.
Como todos os pacotes transmitidos são listados, a informação desejada pode ser
destacada através dos filtros que o programa define. Para auxiliar no projeto,
destacaram-se os seguintes pacotes:
os solicitados a partir do endereço de IP do cliente e recebidos pelo endereço de
IP do servidor proxy, e vice-versa; e
os solicitados a partir do endereço do IP do servidor proxy e recebidos pelo
endereço de IP do servidor de origem, e vice-versa.
Desta forma, verificou-se se todos os pedidos pelos Fragmentos de vídeo, que se
seguiram ao pedido pelo arquivo de manifest, estavam sendo realizados corretamente.
Fig. 4.2: Resultado da execução do Wireshark mapeando a comunicação estabelecida pelo servidor proxy.
Entre outros itens, são exibidos o instante de tempo em que o pacote foi trafegado,
o IP de origem, o IP de destino e tipo de protocolo de comunicação utilizado.
49
É importante salientar, ainda, que o Wireshark também atuou na verificação do
funcionamento da cache, pois os pedidos são listados junto ao instante de tempo em que
os mesmos ocorreram. Assim, foi possível atestar o baixo tempo de latência entre os
pedidos do cliente ao servidor proxy.
Sobre o tempo de latência, o Wireshark auxiliou, por fim, na solução de um dos
erros de execução, em que o intervalo de tempo entre os pedidos por Fragmentos de
vídeo do cliente para o servidor proxy tornava-se crescente conforme a mídia era
reproduzida.
4.3 – Git
Uma das características importantes deste Projeto de Graduação é que toda sua
concepção se deu em ambiente de desenvolvimento, no qual a reutilização de códigos já
existentes e a disponibilização dos novos códigos implementados é primordial. Outra
premissa comum neste ambiente de programação é a preocupação com a segurança dos
códigos, no sentido de evitar perdas das alterações realizadas e restaurar os códigos para
um estado anterior, quando se conclui que as modificações foram inadequadas. Por fim,
é interessante que todo o trabalho esteja acessível de qualquer computador utilizado
pelos programadores envolvidos, de tal forma que a cópia dos códigos em nuvem torna-
se fundamental.
Para atender a todos estes requisitos e a outros não citados, a solução é o uso de
um sistema de controle de versão. Para este projeto, o sistema escolhido foi o Git,
categorizado como um sistema distribuído de controle de versão. Através dele, foi
possível recuperar todo o projeto original e salvar as alterações parciais com a certeza
de que, caso alguma modificação não atingisse o resultado esperado, o projeto inicial
não seria prejudicado. A documentação do Git pode ser vista em [7].
Particularmente para implementar as mudanças descritas no Capítulo 3, uma das
ferramentas do Git foi essencial. Trata-se do comando merge, que compara os
documentos de dois estados do mesmo projeto, destacando as diferenças encontradas
em todos os arquivos. Desta forma, os métodos e as funções modificadas substituíram
50
seus correspondentes originais de forma eficiente, minimizando eventuais erros de
edição de texto.
4.4 – GDB
Em todo projeto envolvendo programação de software ocorre uma etapa de
depuração do código, em que rotinas de testes são realizadas a fim de se identificarem
possíveis erros em tempo de execução. Entre práticas comuns a testes de execução estão
a exibição dos conteúdos de determinados objetos em tela e a implementação de testes
automatizados. As informações obtidas, independente do método escolhido, devem ser
interpretadas pelo programador para que ele possa adotar os procedimentos necessários
para a correção de seu código.
No entanto, em projetos extensos, torna-se interessante o uso de ferramentas de
depuração externas ao código que possam simular a execução do programa a partir de
determinados estados ou verificar, posteriormente à sua ocorrência, qual variável cujo
acesso resultou em uma falha de segmentação – um dos erros de execução mais típico e
de depuração mais trabalhosa. A ferramenta escolhida para este projeto foi o GDB
(GNU5 Debugger) [8].
Embora possua inúmeros recursos, para este projeto, o GDB foi utilizado apenas
para determinação dos elementos responsáveis por falhas de segmentação. Este
procedimento é dado da seguinte maneira:
1. a falha de segmentação gera um arquivo de core dump;
2. a partir do arquivo de core dump e do arquivo executável gerado pela
compilação do projeto Asio Proxy Async – proxy –, a interface em linha de
comando do GDB pode ser iniciada, através do comando gdb proxy core;
3. na interface aberta, o comando de back trace – bt – é executado, de modo que
todos os procedimentos salvos no arquivo de core dump são revelados, do mais
recente para o mais antigo; e
5GNU é um acrônimo recursivo para o sistema operacional baseado em Unix e de código aberto,
significado GNU's Not Unix.
51
4. determina-se o elemento responsável pela falha de segmentação como a última
tentativa de execução de um método pertencente a uma classe definida no
projeto. A chamada deste método estará identificada pelo arquivo e pela linha de
código em que a mesma ocorreu.
Graças a este procedimento, as falhas de segmentação ocorridas puderam ser
resolvidas com sucesso e de maneira eficiente.
Detalhadas as ferramentas que auxiliariam na elaboração do projeto, o próximo
capítulo o finaliza, discorrendo sobre os resultados obtidos e apresentando as
conclusões.
52
Capítulo 5
Resultados e Conclusões
a
No capítulo introdutório, foi explanado o problema com o qual este projeto de
graduação lida: a adaptação de um servidor proxy especializado em vídeo segmentado
para interpretar pedidos por Fragmentos no padrão HDS e em múltiplas taxas.
Um dos objetivos especificados foi tornar o servidor proxy capaz de lidar com
quaisquer vídeos a serem transmitidos no padrão HDS. Para isto, o arquivo de
metadados, chamado de arquivo de manifest, deveria ser lido e compreendido, conforme
o capítulo 2 apresenta. Assim, informações comuns a todas as mídias transmitidas
segundo o HDS poderiam ser obtidas para o cacheamento dos vídeos.
Para manter a consistência e o funcionamento do projeto original, modificações
pontuais em todas as unidades de compilação que o constituem tiveram de ser
realizadas. Estas mudanças são descritas no capítulo 3 e representam a etapa mais
importante deste projeto de graduação.
Em todas as etapas do projeto, outras ferramentas precisaram ser utilizadas para
agilizar a implementação das mudanças necessárias e avaliar qual a melhor solução a
ser tomada. O capítulo 4 indicou as principais destas ferramentas, fundamentais para
que o projeto chegasse à sua conclusão.
Generalizando, este projeto de graduação não possui caráter expositivo, de modo
que os resultados não se apresentam através de valores. Dentro do problema proposto, o
funcionamento do servidor proxy em sua função primordial se manteve, com o
acréscimo de realizar o cacheamento de qualquer vídeo no padrão HDS de tal forma a
armazenar todas as representações de uma mesma mídia como um único vídeo e a
responder ao cliente com o Fragmento da taxa solicitada, sem prejudicar o
sequenciamento da reprodução.
Para validar os resultados, foram realizados testes com vídeos segmentados
segundo o HDS, reproduzidos a partir do Flowplayer [9], desenvolvido em JavaScript e
executado através do navegador web Mozilla Firefox. Foram utilizados, primeiramente,
53
cinco vídeos de duas Representações cada e um único Segmento e três vídeos de uma
única Representação e um único Segmento, a maioria deles obtidos em [10].
O único vídeo não encontrado em [10] desta primeira etapa de testes foi um
filme de cerca de três horas, com uma única Representação e um único Segmento, o
qual, inclusive, era utilizado para os testes do servidor proxy original. O mesmo vídeo
serviu para identificar eventuais atrasos que a execução do servidor proxy poderia
provocar. A falta de sincronismo entre áudio e vídeo, por exemplo, um dos efeitos mais
perceptíveis, seria realçada para um vídeo desta extensão.
Em seguida, para verificar melhor a capacidade do servidor proxy de lidar com
variação entre as múltiplas taxas disponibilizadas para uma mesma mídia, utilizou-se o
programa f4fPackager [11] para segmentar vídeos segundo o HDS. Assim, geraram-se
vídeos de três, quatro e cinco taxas diferentes, podendo-se observar, através do
Wireshark e de informações exibidas na linha de comando, a mudança de representação
nos pedidos do cliente conforme a reprodução avançava. Concluiu-se que o reprodutor,
por padrão, iniciava com a mais baixa taxa disponível, elevando-a após verificar a
velocidade de transmissão que a rede permitia a reprodução sem interrupções.
Apesar de a importância de se lidar com vídeos segmentados em múltiplas taxas
já ter sido amplamente discutida, sobretudo no capítulo 1, pode-se pensar, ainda, em
outras aplicações nas quais o entendimento pelo servidor proxy destas diversas
representações como membros de um mesmo vídeo é essencial, como, por exemplo:
em transmissões de conteúdo ao vivo, em que a conexão entre o cliente e o
servidor proxy se mantém ativa, mas os Fragmentos de vídeo são gerados em
tempo real, de tal forma que o servidor proxy precisa da informação de que se
trata de um mesmo vídeo, para que uma nova conexão não seja registrada, com
o risco de provocar atrasos na reprodução da mídia; e
para a implementação de um sistema de cache compartilhada, em que os clientes
que assistirem ao mesmo vídeo podem acessar os Fragmentos já cacheados por
um cliente anterior, reduzindo o uso de memória do servidor.
Desta forma, sob o ponto de vista da Engenharia Eletrônica, a análise do
problema foi realizada, os objetivos orientadores do projeto foram definidos e as rotinas
de programação necessárias foram implementadas. Os conceitos aprendidos nas
disciplinas da faculdade realizaram, também, seu papel, tanto nos procedimentos
54
inerentes à estruturação de um projeto de Engenharia quanto na implementação
propriamente dita do mesmo. Assim, todas as metas estabelecidas acerca do projeto de
graduação foram atingidas.
Este capítulo concluiu, portanto, o relatório. O próximo e último capítulo tratará
de atividades futuras associadas a este projeto de graduação.
55
Capítulo 6
Trabalhos Futuros
a
Pensando no cenário atual da transmissão de vídeo pela internet, novos padrões
estão sendo desenvolvidos e cada vez mais adotados no mercado, e esta tecnologia
tende a ser mais amplamente explorada. Neste sentido, outras duas implementações de
streaming adaptativo via HTTP surgiram em paralelo ao HDS: o MSS (Microsoft
Smooth Streaming), da Microsoft ©; e o HLS (HTTP Live Streaming), da Apple ©.
Posteriormente, estas e outras empresas do setor se reuniram para definir o que
seria considerado o padrão oficial em streaming adaptativo, o MPEG DASH (MPEG6
Dynamic Adaptive Streaming over HTTP). No momento, considera-se que estas quatro
implementações dividem o mercado.
Desta forma, o principal trabalho futuro associado a este projeto de graduação é
realizar novas adaptações ao servidor proxy para que ele possa lidar com segmentos de
mídia transmitidos segundo cada um destes padrões, principalmente o MPEG DASH,
realizando o cacheamento correto e obtendo as informações prévias dos respectivos
arquivos de metadados de cada padrão.
Também é importante salientar que o projeto foi finalizado como uma versão de
testes. Seria interessante definir modificações para que uma versão comercial pudesse
ser elaborado, com a possível criação de uma interface gráfica.
Além destas novas adaptações, outras etapas do processo de segmentação do
vídeo podem ser avaliadas. Uma ideia que poderia otimizar ainda mais o consumo de
memória seria a segmentação das múltiplas taxas do vídeo em tempo real, de acordo
com as necessidades do usuário, ao invés de armazená-las todas no servidor de origem.
O poder de processamento do servidor seria mais exigido, mas isto poderia ser
compensado com uma das aplicações citadas no capítulo 5, a memória cache
compartilhada.
6MPEG é a sigla para Motion Pictures Experts Group.
56
Estes projetos já estão sendo pensados e provavelmente gerarão outros trabalhos
em breve. Assim, encerra-se este relatório de Projeto de Graduação em Engenharia
Eletrônica e de Computação.
57
Bibliografia
[1] “Adobe Flash Video File Format Specification”, Version 10.1, Adobe Systems In-
corporated, Califórnia, Agosto 2010.
[2] “Boost C++ Libraries”, http://www.boost.org/, 2014, (Acesso em 29 de julho de
2014).
[3] World Wide Web Consortium (W3C), “Extensible Markup Language (XML)”,
http://www.w3.org/XML/, 2014, (Acesso em 29 de julho de 2014).
[4] “Base64 Decode and Encode – Online”, http://www.base64decode.org/, 2014,
(Acesso em 29 de julho de 2014).
[5] “Base64 Online - base64 decode and encode”, http://www.motobit.com/util/base64-
decoder-encoder.asp, 2014, (Acesso em 30 de julho de 2014).
[6] LAMPING, U., SHARPE, R., WARNICKE, E., Wireshark User's Guide for
Wireshark 1.99, NS Computer Software and Services P/L, 2014.
[7] CHACON, S., Pro Git, Julho 2009.
[8] STALLMAN, R., PESCH, R., SHEBS, S., et al., “Debugging with GDB – The GNU
Source-Level Debugger”, Boston, Free Software Foundation, 10ª ed, 2014.
[9] “Flash Video Player for the Web: Flowplayer”, http://flash.flowplayer.org/, 2014,
(Acesso em 25 de agosto de 2014).
[10] “Videos from the World’s Best Conferences and Events”, http://www.fora.tv, 2014,
(Acesso em 25 de agosto de 2014).
[11] “Adobe HTTP Dynamic Streaming * Packaging on-demand media”,
http://help.adobe.com/en_US/HTTPStreaming/1.0/Using/WS9463dbe8dbe45c4c-
c126f3b1260533756d-7ffc.html, 2014, (Acesso em 26 de agosto de 2014).
[12] “UML – Diagrama de classes”, http://www.macoratti.net/net_uml1.htm, 2014,
(Acesso em 25 de agosto de 2014).
58
Anexo A
Exemplo de arquivo de manifest
<manifest>
<id>
2012-08-20_pagels_long_now-384kbps-FORAcast-13251
</id>
<streamType> recorded </streamType>
<duration> 223.44562222222223 </duration>
<bootstrapInfo profile="named" id="bootstrap3317">
AAAB+2Fic3QAAAAAAAAAGQAAAAPoAAAAAAADaKcAAAAAAAAAAAAA
AAAAAQAAABlhc3J0AAAAAAAAAAABAAAAAQAAADgBAAABtmFmcnQAA
AAAAAAD6AAAAAAaAAAAAQAAAAAAAAAAAAAaLAAAAAIAAAAAAAAa
CgAADBwAAAADAAAAAAAAJgUAAAzkAAAABQAAAAAAAEAQAAAaLAA
AAAYAAAAAAABaGgAADOQAAAAKAAAAAAAAjjAAABosAAAACwAAAAA
AAKg6AAAM5AAAAA8AAAAAAADcUAAAGiwAAAAQAAAAAAAA9loAAAz
kAAAAFAAAAAAAASpwAAAaLAAAABUAAAAAAAFEegAADOQAAAAZAAA
AAAABeJAAABosAAAAGgAAAAAAAZKaAAAM5AAAAB4AAAAAAAHGsAA
AGiwAAAAfAAAAAAAB4LoAAAzkAAAAIwAAAAAAAhTQAAAaLAAAACQA
AAAAAAIu2gAADOQAAAAoAAAAAAACYvAAABosAAAAKQAAAAAAAnz6A
AAM5AAAAC0AAAAAAAKxEAAAGiwAAAAuAAAAAAACyxoAAAzkAAAAM
gAAAAAAAv8wAAAaLAAAADMAAAAAAAMZOgAADOQAAAA3AAAAAAA
DTVAAABosAAAAOAAAAAAAA2daAAABLAAAAAAAAAAAAAAAAAAAAA
AA
</bootstrapInfo>
<media streamId="2012-08-20_pagels_long_now-384kbps-FORAcast-13251"
url="2012-08-20_pagels_long_now-384kbps-FORAcast-13251" bitrate="300"
bootstrapInfoId="bootstrap3317">
<metadata></metadata>
59
</media>
<bootstrapInfo profile="named" id="bootstrap6903">
AAADC2Fic3QAAAAAAAAAKgAAAAPoAAAAAAADZ7QAAAAAAAAA
AAAAAAAAAQAAABlhc3J0AAAAAAAAAAABAAAAAQAAADgBAAACxmFm
cnQAAAAAAAAD6AAAAAArAAAAAQAAAAAAAAAAAAARMAAAAAMAAA
AAAAAiaAAAEGgAAAAEAAAAAAAAMtUAAAzkAAAABQAAAAAAAD+8AA
ARMAAAAAYAAAAAAABQ8AAADOQAAAAHAAAAAAAAXdgAABEwAAAA
CQAAAAAAAIBAAAAM5AAAAAoAAAAAAACNKAAAETAAAAAMAAAAAA
AAr5AAAAzkAAAADQAAAAAAALx4AAARMAAAAA8AAAAAAADe4QAADO
QAAAAQAAAAAAAA68gAABEwAAAAEQAAAAAAAPz8AAAM5AAAABIAA
AAAAAEJ5AAAETAAAAAUAAAAAAABLEwAAAzkAAAAFQAAAAAAATk0A
AARMAAAABcAAAAAAAFbnAAADOQAAAAYAAAAAAABaIQAABEwAAAA
GQAAAAAAAXm4AAAM5AAAABoAAAAAAAGGoAAAETAAAAAcAAAAAA
ABqQgAAAzkAAAAHQAAAAAAAbXwAAARMAAAAB8AAAAAAAHYWAAA
DOQAAAAgAAAAAAAB5UAAABEwAAAAIgAAAAAAAgepAAAM5AAAACM
AAAAAAAIUkAAAETAAAAAkAAAAAAACJcQAAAzkAAAAJQAAAAAAAjKs
AAARMAAAACcAAAAAAAJVFAAADOQAAAAoAAAAAAACYfwAABEwAAA
AKgAAAAAAAoRkAAAM5AAAACsAAAAAAAKRTAAAETAAAAAtAAAAAAA
Cs7UAAAzkAAAALgAAAAAAAsCcAAARMAAAAC8AAAAAAALR0AAADOQ
AAAAwAAAAAAAC3rgAABEwAAAAMgAAAAAAAwEgAAAM5AAAADMAAA
AAAAMOCAAAETAAAAA1AAAAAAADMHEAAAzkAAAANgAAAAAAAz1YA
AARMAAAADcAAAAAAANOjAAADOQAAAA4AAAAAAADW3QAAAwcAAA
AAAAAAAAAAAAAAAAAAAA=
</bootstrapInfo>
<media streamId="2012-08-20_pagels_long_now-768kbps-FORAcast-13251"
url="2012-08-20_pagels_long_now-768kbps-FORAcast-13251" bitrate="600"
bootstrapInfoId="bootstrap6903">
<metadata></metadata>
</media>
</manifest>