adaptaÇÃo de servidor proxy para...

59
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

Upload: dinhnguyet

Post on 22-Apr-2018

220 views

Category:

Documents


2 download

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>