http://www.niksula.cs.hut.fi/projects/ohtace/documents/te.html
CVS info: $Id: te.html,v 1.77 1997/04/22 09:58:11 mtuisku Exp $
0. Yhteenveto
1. Johdanto
2. Järjestelmän yleiskuvaus
3. Arkkitehtuurin kuvaus
4. Moduli (ja prosessi) -kuvaukset
5. Modulien toteutuksen kuvaus
Internet-TV:ssä käyttöliittymä pohjautuu Tcl/Tk toolkittiin. Karkea modulijako on kuten nykyisissä sovelluksissa: äänelle ja kuvalle on omat prosessit. Käyttöliittymä on kuitenkin molemmille yhteinen ja mahdollisimman helppokäyttöinen. Prosessit kommunikoivat yksinkertaisen protokollan avulla käyttäen socketteja. Myös ennen erillisenä toiminut kanavavalitsin on integroitu kuvaa käsitelevään prosessiin.
Toteutuksessa käytetään olemassaolevien työkalujen luokkahierarkiaa soveltuvin osin mahdollisimman laajalti. Näistä on kuitenkin riisuttu pois puhtaasti lähettämiseen käytettävät luokat ja metodit.
Ohjelman tarkoitus on vastaanottaa ääntä ja liikkuvaa kuvaa ja esittää se käyttäjälle tietokoneen kuvaruudulta ja kaiuttimista. Tarkoitus on, että mahdollisimman moni kykenisi käyttämään tätä ohjelmaa. Käyttäjiin kuuluvat mm. 5-vuotiaat lukutaidott omat lapset, kieliä taitamattomat mongolit ja kaukonäköiset vanhukset. Näiden käyttäjäryhmien palvelu ei kuitenkaan tarkoita sitä, etteikö ohjelma olisi hyödyllinen ja mukava käyttää myös bittivirtuoosien mielestä.
Ohjelmatyöhön liittyvistä termeistä on olemassa oma dokumenttinsa.
Tämä dokumentti sisältää seuraavat luvut:
0. Yhteenveto
1. Johdanto
2. Järjestelmän yleiskuvaus: Multicast,
käyttö- ja ohjelmistoympäristöt, toteutuksen reunaehdot, käyttöliittymä,
asetusten tallennus
3. Arkkitehtuurin kuvaus: Yleisrakenne
4. Moduli (ja prosessi) -kuvaukset:
Kuvan käsittely, äänen käsittely, käyttöliittymän ja toteutuksen rajapinta,
kanavien haku
5. Modulien toteutuksen kuvaus: Käyttöliittymä,
kuvan käsittely, äänen käsittely, pää- ja ääniprosessin välinen protokolla, kanavien haku
Perinteinen Internet-liikenne on ollut unicast-liikennettä, jossa lähetyksellä on aina yksi lähettäjä ja yksi vastaanottaja. Mikäli on haluttu lähettää sama viesti monelle vastaanottajalle, on se jouduttu lähettämään monta kertaa. Tämä kuluttaa erittäin paljon siirtokaistaa käytettäessä muutenkin raskaita video- ja audio-sovelluksia. Multicastin avulla säästetään merkittävästi verkon kapasiteettia tämäntyyppisissä sovelluksissa.
Käyttämällä multicast-liikennettä, jossa on yksi lähettäjä, mutta monta vastaanottajaa. Tällöin sama viesti liikkuu täsmälleen yhtenä kopiona lähettäjältä eteenpäin, kunnes se vasta lähellä vastaanottajia kopioidaan ja lähetetään kullekin vastaanottajalle erikseen. Tämä säästää tiedonsiirtokapasiteettia.
Multicast on erinomaisen sovelias lähetystapa silloin, kun lähetettävä tietomäärä on suuri, ja saman tieto halutaan jakaa sellaisenaan useille vastaanottajille. Sillä voidaan lähettää mm. liikkuvaa kuvaa ja ääntä, jotka vaativat suhteellisen paljon tiedon siirtokapasiteettia. On olemassa myös multicastia hyödyntäviä työryhmäohjelmistoja, jossa monet käyttäjät jakavat vaikkapa yhteisen "liitutaulun" kuvaruudulla. Taululle voi sitten piirrellä kuvioita ja tekstiä ja ne välittyvät kaikille osanottajille saman laisina.
Internet-TV-työssä käsitellään IP-multicastia , joka on internet-protokollan D-luokan osoitteilla toteutettu multicast. IP-multicastilla lähetetään ja vastaanotetaan mm. videokuvaa ja ääntä.
Kuva pakataan jollain pakkausmetodilla (H.261, MPEG, lisää kuvakoodauksesta), samoin ääni (PCM, ADPCM, DVI, LPC, GSM, lisää äänikoodauksesta). Kuva ja ääni puretaan vastaanottopäässä, eli Internet-TV:s sä. Välitetyt kuva- ja äänivirta synkronoidaan RTP- ja RTCP-protokollilla. Vastaanotetut pakatut kuva- ja äänivirrat puskuroidaan muutaman sekunnin ajalta, jotta tiedonsiirtoyhteydessä mahdollisesti esiintyvät häiriöt voidaan paikata puskurista esitettävällä tiedolla.
Käyttöympäristö on tavanomainen ikkunoitu käyttöjärjestelmä. Tässä vaiheessa rajoitumme UNIX (Solaris 2.5) -käyttöjärjestelmään ja X11 käyttöliittymäympäristöön.
Tavoitteena kuitenkin on, että ohjelma kyettäisiin vähäisellä työmäärällä siirtämään myöhemmin muihin käyttöympäristöihin. Tähän pyritään käyttämällä käyttöjärjestelmäriippumattomia toteutustyökaluja. Tällä hetkellä työkaluja on ainakin seuraaviin käyttöjärjestelmiin: Solaris, SGI, DEC OSF, HP-UX, FreeBSD, NetBSD, Linux, Windows 95 ja Windows NT. Macintosh ympäristöihin ei toistaiseksi ole saatavilla ip-multicast tukea.
C/C++-kääntäjänä käytetään gcc-kääntäjän versiota 2.7.2.
Käyttöliittymä luodaan Tcl-kielellä ja Tk-kirjastolla käyttäen viimeisintä stabiilia versiota, joka on siirretty useimpiin käyttöjärjestelmiin. Tällä hetkellä uusimmat versiot ovat Tcl 7.6 ja Tk 4.2, mutta ainakin Windowsiin on saatavana vasta Tcl 7.5 ja Tk 4.1. Tärkeintä ei ole käyttää kaikkia uusimpia ominaisuuksia, vaan sellaisia, jotk a ovat helposti siirrettävissä mahdollisimman moneen ympäristöön.
Työssä pyritään hyödyntämään mahdollisimman paljon valmista lähdekoodia. Tällaista on ohjelmissa vic (liikkuvan kuvan katseluohjelma) ja vat (äänenvälitysohjelma). Lisäksi ohjelmasta sdr etsitään rutiineja kanavavalikon toteuttamiseen. Ohjelmista käytettävät koodit pyritään käyttämään mahdollisuuksien mukaan kokonaisuuksina, koska toisen tekemään koodiin koskeminen on usein työlästä ja riskialtista. Valmis koodi on rakennettu olio-ohjelmoinnin periaatteita hyödyntäen, mikä helpottaa sen käyttöönottoa tässä projektissa.
Käyttäjän koneelta Internet-TV vaatii, että siinä on käytössä IP-multicast. Esiasennettua Tcl/Tk ympäristöä ei tarvita, sillä ohjelmat linkitetään staattisesti, jolloin tarvittavat kirjastorutiinit ovat ohjelman binaarissä mukana.
Ohjelmakoodin ja toiminnan laadun varmistamiseksi on laadittu erityinen laatudokumentti, jossa kuvataan mm. niitä käytäntöjä, joita toteutuksessa pyritään noudattamaan.
Jotta ip-multicast-lähetyksiä voidaan vastaanottaa, on verkon ylläpidon järjestettävä ip-multicast-reititys siihen verkkosegemnttiin, jossa käytettävä työasema sijaitsee. Käytännössä tämä tapahtuu tekemällä reitittimiin konfiguraatiomuutoksia. Jatkossa tilanne tulee kehittymään niin, että ip-multicast reititys on oletusasetuksena reitittimissä.
Multicast-liikenne voidaan toteuttaa kaikissa verkkoarkkitehtuureissa, joissa ip-liikenne on mahdollista. Paikallista siirtokaistaa ip-multicast-liikenne vie seurattavasta materiaalista riippuen parista kymmenestä kbit/s aina MPEG:in 2 Mbit/s asti. Muomattavaa on kuitenkin, että tämä on riippumaton saman lähetyksen seuraajien lukumäärästä. Verkon siirtoviiveiden kuitenkin tulisi olla mahdollisimman lyhyitä ja ennenkaikkea vakioita, jotta esim. äänen laatu ei tämän johdosta kärsi.
Reaaliaikainen kuvan ja äänen yhtäaikainen purku ja tarvittavat muut kuvankäsittelyoperaatiot (esim. kuvan koon skaalaus tai kirkkauden säätö) vaativat kohtuullisen paljon laskentatehoa. Työssä ei ole tavoitteena optimoida suorituskykyä, vaan tehdä joustavia ratkaisuja ja luottaa siihen, että konetehojen kasvu jatkuu. Toteutuksen tulisi toimia sujuvasti ainakin Sun Ultra-Sparc arkkitehtuurin päällä.
Kuvasta, kanavavalitsimesta ja käyttöliittymästä vastaa yksi pääprosessi. Tämä vastaa myös lähetysilmoitusten keräämisestä kanavanvalitsimeen multicast-ilmoituskanavalta. Pääprosessi käynnistää toisen prosessin, joka vastaa äänen vastaanotosta ja purusta. Tämä prosessi käynnistetään omasta tiedostostaan. Sillä ei ole omaa käyttöliittymää, vaan pääprosessi ohjaa tätä käynnistyksen yhteydessä parametrina annetavan tcp-portin kautta. Liittymänä käyetään normaalia socket-rajapintaa. Yhteydellä käytetään yksinkertaista protokollaa eri parametrien välittämiseen.
itv.setup
muodossa
asetus=arvo
. Ohjelma lukee asetukset käynnistyksen
yhteydessä. Mikäli jotain arvoa ei ole, valitaan sopiva oletusarvo.
Arvot on tarkistettava; mikäli asetustiedostossa ei ole järkevää arvoa,
turvaudutaan oletusarvoon ja korvataan viallinen arvo tällä.
Asetukset talletetaan niiden muuttamisen yhteydessä.
Internet-TV:n pohjana käytetään VIC, VAT ja SDR ohjelmistoja. Näiden rakenne määrää hyvin pitkälle Internet-TV ohjelmiston rakenteen, varsinkin jos halutaan pysyä projektille sopivassa työmäärässä.
Ko. ohjelmistojen lähdekoodin määrä on hyvin suuri:
wc -l *.cc *.c *.h *.tcl ======================== vic 2.8 67833 total vat 4.0b2 60141 total sdr 2.3a1 31060 total
Yhdistettynä koodin hyvin niukkaan dokumentaatioon, koodiin tutustuminen on suhteellisen hankalaa ja aikaavievää. Koodin ulkonäkö on kuitenkin siisti, sisennykset ovat kohdallaan eikä ylipitkiä rivejä juuri ole. Lukuisten lyhyiden ja dokumentoimattomien muuttujanimien käyttö aiheuttaa koodiin tutustuvalle kuitenkin melkoista haittaa.
Edellämainituista seikoista johtuen, sopivin Internet-TV:n toteutusstrategia onkin käyttää em. ohjelmistoja mahdollisimman suurina komponentteina. Tämä johtaa mm. siihen, että videon ja äänen käsittely toteutetaan erillisissä prosesseissa.
Seuraavassa on selitetty vicin puhtaat virtuaaliluokat. Päätimme selittää vain puhtaat virtuaaliluokat, koska ne kuitenkin vicin tapauksessa määrittelevät suurimman osan jäsenfunktiosta, aliluokkien määriteltäväksi jää ainoastaan yhden tai pahimmassa tapauksessa kolmen jäsenfunktion määrittely. Nämä ylemmän tason virtuaaliluokat muodostavat jonkinlaisen API:n. Emme ole kuvailleet kaikkien jäsenfunktioiden tehtäviä, tälläisiä jäsenfunktiota ovat ne jotka palauttavat tai asettavat jonkun suojatun tai yksityisen jäsenmuuttujan arvon.
Vicin luokkien nimet kuvailevat jo itsessään sen mikä niiden tehtävä on. Myös muuttujien nimikäytäntö on hyvin johdonmukaista, ja tämä helpottaakin koodin ymmärtämistä.
Luokkahierarkia kuvina: osa1 (koko kuvan vasen puolisko) ja osa2 (koko kuvan oikea puolisko).
Luokkahierarkia tulostuskelpoisina postscript-tiedostoina: osa1, osa2.
Luokka: Render (puhdas virtuaaliluokka) kuvaus: Luokan tarkoitus tarjota peruskomponentit on tulostaa sisään tulevaa kuvadata, joillekin tuetuille näyttöläitteille, esim. X-windows käy hyvin. Luokan esi-isät: Module, TclObject ja Timer. Luokan lapset: BlockRenderer, WindowRenderer, WindowDitherer, HiWindowRenderer, MonoWindowRenderer, PseudoWindowRenderer, DitherWindowRenderer, EDWindowRenderer, GrayWindowRenderer, QuantWindowRenderer, TrueWindowRenderer, YuvWindowRenderer, JvOutboardAssistor, JvWindowAssistor, PlxWindowAssistor, VLOutboard, VLOutboard_411, VLOutboard_422. Luokan metodit: Command: tarkistaa onko argv:ssä joko update-interval tai color optioita. Jos näin on niin ne niiden arvot sijoitetaan vastaaviin sisäisiin muuttujiin. Muutoin annetaan Module::commandin parsia argv:tä. Setinterval: asettaa kuvan päivitysvälin. Ja päivittää instannsin timeria. Luokka: Module (puhdas virtuaaliluokka) kuvaus: Luokan tarkoitus on tarjota peruskomponentit kuvan esittämiseen (kuvan leveys, korkeus, kehysten koko ja datavirran tyyppi). Luokan esi-isät: TclObject. Luokan lapset: Compositor, JpegTranscoder, Renderer, TransmitterModule. Luokan metodit: Command: tarkistaa onko argv:ssä joko frame-format tai target optiota. Jos näin niin niiden arvot sijoitetaan vastaaviin sisäisiin muuttujiin. Muutoin annetaan Module::commandin parsia argv:tä. Consume: on puhdas virtuaalifunktio, jonka tehtävä on tarjota totetus päivitykseen niille videokehyksille jotka mahdollisesti päivitetään. Päivitys alkorytmit vaihtelevat sen mukaan minkälainen videokehys on kysessä. Consume toteutetaan varsinaisesti Render luokasta periytyvissä aliluokissa. Luokka: Decoder (puhdas virtuaaliluokka) kuvaus: Luokan tarkoitus on tarjota peruskomponentit raa'an kuvadatan muuttamiseksi esitykelpoiseen muotoon. Varsinainen muunnostyö tapahtuu vasta ali-luokissa. Ali-luokissa codec_ jäsen muuttuja osoittaa varsinaiseen dekoodaus metodiin. luokan esi-isät: PacketHandler, TclObject. luokan lapset: CosmoDecoder, H261Decoder, MotionJpegDecoder, NullDecoder, PlaneDecoder, RTPv1H261Decoder Luokan metodit: Command: toimii kuten samalla tavalla kuin, Module::Command, mutta tarkistaa onko optio joko width, height, info, stat, decimation, redraw, playout, color, attach, detach vai histogram. Decimation kertoo sen millaista värikonversiota käytetään (411 tai 422). Histogram kertoo minkälainen väriskaala kyseisellä oliolla on käytössä. Attach: lisää argumenttina annetun Render olion sisäiseen engine_ nimiseen linkitettyyn listaan. Redraw: käy engine_ listan Render oliot läpi asettaen jokaisen olion now_ muuttujan nollaksi. Tämän jälkeen kutsutaan Render_frame jäsenfunktiota, jonka tehtävänä on päivittää engine_ ketjua siten, että ne oliot joiden aikaleimat ovat muuttumassa menneisyydestä tulevaisuuteen ja siitä nykyhetkeen päivitetään. Luokka: PacketHandler (puhdas virtuaaliluokka) Kuvaus: Tarjoaa perusominaisuudet erilaisten kuvapakettidatojen hoitoon. Luokan lapset: Decoder. Luokan esi-isät: TclObject. Luokan metodit: Recv: on puhdas virtuaalifunktio, joka toteutetaan vasta Decoder-luokan lapsissa. Recv-funktio vastaa kuvapakettidatan vastaanotosta. Luokka: SessionManager (puhdas virtuaaliluokka) Kuvaus: Tarjoaa perusominaisuudet median katselua varten. Luokan esi-isät: Luokan lapset: AudioSessionManager, VideoSessionManager, RTPv1SessionManager. Luokan metodit: alloc_srcid: luo sisään tulevalle datalle oman uniikin id numeron käyttäen aikaa, prosessi- ja prosessiryhmän numeroa sekä argumenttinä annettavaa osoittetta. build_bye: laittaa istunnon lopetusta tarkoittavat arvot argumenttina annettaviin otsikkokenttiin. build_sdes: rakentaa lähetystä kuvaavan tiedon numeron. Eri pakettinumeroille annetaan oma arvo seuraavasti: joka 0:s ja 4:s paketti 'email'-arvo joka toinen paketti 'note'-arvo joka kuudes paketti 'tool'-arvo parittomiin numeroihin 'name'-arvo. check_format: puhdas virtuaalifunktio jonka tehtävänä tarkistaa minkälaista dataa tulee sisään. Tämä funktio toteutetaan SessionManagerin alaluokissa. command: parsii argv:tä samalla tavalla kuin yllä olevissakin luokissa kuitenkin sisällä eroituksella, että parsittavia optiota ovat seuraavat: active, local-addr-heuristic, stats, nb, nf, np, name, email, random-srcid, data-net, ctrl-net, max-bandwith, conf-id, data-bandwith, mtu ja loopback. Jollei argv sisällä jotakin edellä olevaa optiota, niin silloin se annetaan Trasmitter::command:n käsiteltäväksi. demux, tarkistaa onko sisään tuleva data aito datapaketti vaiko otsikkopaketti, ja käsittelee paketin asianmukaisesti. parse_*. Nämä funktiot tarkistavat onko sisään tuleva paketti halutun muotoinen. recv: Tämä ylikuormitettu funktio ottaa dataa vastaan joko kontrolliportista tai sitten dataportista. Luokka: IOHandler (puhdas virtuaalifunktio) Kuvaus: Luokan tarkoitus on tarjota menetelmät sisään tulevan ja ulos lähtevän datan matalan tason käsittelyyn. Luokan esi-isät:. Luokan lapset: Communicator, DataHandler, CtrlHandler. Luokan metodit: link: luo Tk-käyttöliittymää varten soketin, jolla data käyttöliittymän ja matalan tason rutiinien välillä kulkee. unlink: tuhoaa link-funktion avulla luodun soketin. dispatch: puhdas virtuaalifunktio. Dispatch toteutetaan IOHandlerin alaluokissa. Dispatchin tehtävä on välittää eri tavoin, riippuen ali-luokasta, matalan tason data ylemmälle kerrokselle. Luokka: Source Kuvaus: Source tarjoaa ominaisuudet lähdedataan sijoitettaviin aikaleimojen käsittelyyn. Luokan esi-isät: TclObject. Luokan lapset:. Luokan metodit: useita funktioita aikaleimojen käsittelyyn. activate: asettaa busy_ lipun päälle. Luokka: SourceManager kuvaus: SourceManager tarjoaa ominaisuudet Source olioiden käsittelyyn. Luokan esi-isät: TclObject. Luokan lapset:. Luokan metodit: CheckActiveSources: käy läpi sources_ osoittamaa linkittettyä listaa ja tarkistaa onko Source oliot aktiivisia. Jos olio ei ole aktiivinen, niin silloin CheckActiveSources poistaa sen. compare: vertailee kahta Source oliota ja palauttaa 0 jos Source oliot ovat saman nimisiä muussa tapauksessa palautetaan <> 0. consult: ottaa selville onko argumenttina annettava srcid jo sisäisessä hajautustaulussa. Jos on, niin palautetaan srcid osoittama Source olio, muutoin palautetaan nolla. demux, laittaa tietyn srcid:n hajautustauluun. Tieto virtaa ei hyväksytä ennen kuin on saatu kaksi jarjestyksessä olevaa pakettia. enter: laittaa argumenttina välitetyn Source-olion sources_ nimiseen linkitettyyn listaan seka hashtab_ nimiseen hajautustauluun. lookup: yrittää etsiä järkevästi srcid mukaista Source-oliota. Jos oliota ei löydy niin luodaan uusi olio. lookup_duplicate, yrittää etsiä Source-oliota lähteen verkko-osoitteen mukaan. Jos tälläinen olio löytyy niin tuhotaan sen vanha paikka ja sijoitetetaan se uuten paikkaan, uudella srcid:llä. Tätä funktiota käytetetään silloin kuin lähettävä pää joutuu katkaisemaan yhteyden lyhyeksi aikaa. remove, poistaa Source-olion sekä sources_ listasta ja hastab_ taulusta. sortactive: järjestää aktiiviset Source-oliot aakkosjärjestykseen argumenttinä annettuun puskuriin. Luokka: Network. Kuvaus: Network-luokka tarjoaa rutiinit erilaisiin yhteyden muodostuksiin ja manipulointiin sokettien yms. avulla. Luokan eis-isät: TclObject. Luokan lapset: ForeATM, IPNetwork, rtipChannel. Luokan metodit: command: Toimii kuten yllä olevissakin luokissa, mutta sillä eroituksella, että parsittavia optiota ovat: addr, interface, port, ttl, ismulticast, crypt ja muussa tapauksessa TclObject::command hoitaa argv:n käsittelyn. cpmsg, kopio pirstaloituneena tulevan datan työbufferiin. dorecv, recvfrom-funktion ympärille tehty funktio. Tekee tarvittavat tarkistukset. Argumentteina välitetään recvfromin tarvittsemat parametrit. dosend: send-funktion ympärille tehty funktio. Suorittaa älykkään virheen tarkistuksen sendin palauttamille arvoille. expand_wrkbuf, kasvattaa wrkbuf argumentin verran. nonblock, muuttaan argumenttina annetun soketin ei-blokkaavaaksi (non-blocking). recv: funktion tarkoitus on ottaa vastaan tavaraa rsock_ osoittamasta portista. Jos kyseessä oleva instanssi on salattu niin silloin vastaan otettu tavaran salaus puretaan. send: tämä ylikuormitettu funktio lähettää tavaraa ssock_ osoittamaan porttiin. Jos ko. instannsi on salattu, niin data kopioidaan wrkbuf_iin joka siten lähetetään salattuna eteenpäin. Luokka: Transmitter (puhdas virtuaaliluokka) Kuvaus: Transmitter luokka tarjoaa perusominaisuudet datapakettien lähettämiseen. Luokan esi-isät: TclObject,Timer. Luokan lapset: SessionManager. Luokan metodit: loopback: välittää argumenttina annetun paketin PacketHandler-oliolle tarpeellisten tarkastusten jälkeen. output, Valmistelee argumettina annettavan paketin lähetyskuntoon. Suorittaa myös paketin debbuggaustulostuksen jos 'dump'-lippu on päällä. transmit: tämä on puhdas virtuaalifunktio jonka varsinainen toteutus on SessionManager-luokan heiniä. Perustapauksessa tämä funktio valittaa argumenttina annetun paketin Network-olion send-funktion käsiteltäväksi. release: tämä funktio vapauttaa lähetetyn paketin lähettettävien pakettien listasta. send: tämä funktio tarjoaa lähetyksen keskeytys toiminnon ennen output-jäsenfunktion kutsua.
Äänen käsittely hoidetaan omassa prosessissa, jonka käyttöliittymäprosessi käynnistää fork() + exec() yhdistelmällä antaen komentoriviparametreina tcp-portin, jonka kautta prosessit kommunikoivat. Käytettävät ohjauskomennot on kuvattu kohdassa 2.5.2.
Tässä kohdassa on kuvattu vatin olemassaoleva luokkahierarkia, jota oma toteutuksemme mukailee.
Luokkahierarkia kuvina: osa1 (koko kuvan vasen puolisko) ja osa2 (koko kuvan oikea puolisko). Kuvassa ei ole aivan kaikkia luokkia.
------------------------------------------------------------------ Luokka: IOHandler (puhdas virtuaaliluokka) Kuvaus:sama kuin vic:ssä Kantaluokka: - Johdetut luokat: Audio, DataHandler, GroupIPC Luokan metodit: link: linkkaa tiedostokahvaan callback-funktion, jota kutsutaan, kun tiedoston/socketin tilassa tapahtuu haluttu muutos, esim. uutta dataa on luettavissa unlink: poistaa link:llä tehdyn linkin dispatch: (puhdas virtuaalifunktio) ------------------------------------------------------------------ Luokka:Audio (puhdas virtuaaliluokka) Kuvaus: Kantaluokka erilaisille audiolaitteille Kantaluokat: TclObject, Observable, IOHandler Johdetut luokat: AFAudio, HPAudio, IBMAudio, PCAudio, SGIAudio, SUNAudio, SocketAudio, VoxWareAudio, Win32Audio Luokan metodit: commad: käsittelee tcl-koodista tulevat audio-komennot, joita ovat pääasiassa eri parametrien säädöt Release: sulkee avoimen tiedostokahvan/socketin Obtain: liittää callbackin tiedostokahvan/socketin dispatch: kutsuu audio_handle() funktiota kun kauan kuin uusi frame on valmiina ------------------------------------------------------------------ Luokka: SUNAudio Kuvaus: SUN-spesifisen audiolaitteiston ohjaus Kantaluokka: Audio Johdetut luokat: BSDAudio, SUNDBRIAudio Luokan metodit: command: käsittelee osan tcl-koodista tulevista audio-käskyn parametreista, loput välitetään kantaluokan Audio käsiteltäväksi Obtain: avaa audio-laitteen (esim. /dev/audio) ja kutsuu Audio::Obtain() Release: palauttaa alkuperäiset asetukset ja vapauttaa laitteen, kutsuu Audio::Release() Write: kirjoittaa laitteelle blksize kokoisen blokin audiodataa FrameReady: palauttaa toden, kun puskurissa on uusi sample valmiina Read: palauttaa osoittimen puskurin alkuun setup_device: asettaa audio-laitteelle oikeat parametrit ioctl kutsuilla, kutsutaan Obtain metodista getinfo, setinfo: audio-laitteen parametrit ioctl-komennolla, näitä käytetään lukuisista muista metodeista OutputPort, InputPort: asetetaan laite, jonka kautta ääni luetaan / soitetaan ulos ------------------------------------------------------------------ Samaan tapaan on kantaluokasta Audio johdetut luokat Win32Audio, SGIAudio jne. ------------------------------------------------------------------ Luokka: PacketHandler (puhdas virtuaaliluokka) Kuvaus: jokaiseen aktiiviseen lähteeseen (luokat Source ja SourceManager) liittyy PacketHandler, joka on Decoder luokan kantaluokka Kantaluokka: TclObject Johdetut luokat: Decoder Luokan metodit: pari pientä inline metodia ja puhtaasti virtuaalinen recv ------------------------------------------------------------------ Luokka: Source (sama kuin vic:ssä) Kuvaus: Tietyn lähteen tietojen ja tilastojen käsittely Kantaluokka: TclObject Johdetut luokat: - Luokan metodit: ------------------------------------------------------------------ Luokka: SourceManager (sama kuin vic:ssä) Kuvaus: SourceManager tarjoaa ominaisuudet Source olioiden käsittelyyn Kantaluokka: TclObject Johdetut luokat: - Luokan metodit: init: luo entryn paikalliselle lähteelle command: käsittelee tcl-laajennukselta tulevat komennot lookup: etsii hash-taulusta srcid:tä, jos sopivaa ei löydy, luodaan uusi demux: laittaa vastaanotettavat paketit lähdekohtaisiin jonoihin consult: ottaa selville onko argumenttina annettava srcid jo sisäisessä hajautustaulussa. Jos on, niin palautetaan srcid:n osoittama Source olio, muuten palautetaan nolla CheckActiveSources: käy läpi sources_ osoittamaa linkittettyä listaa ja tarkistaa onko Source oliot aktiivisia. Jos olio ei ole aktiivinen, niin silloin CheckActiveSources poistaa sen. sortactive: järjestää aktiiviset Source-oliot aakkosjärjestykseen argumenttinä annettuun puskuriin remove: poistaa Source-olion sekä sources_ listasta ja hastab_ taulusta ------------------------------------------------------------------ Luokka: Decoder Kuvaus: Kantaluokka erilaisille äänidekoodereille, vain johdetut luokat voivat kutsua tämän luokan konstruktoria Kantaluokka: PacketHandler Johdetut luokat: NullDecoder, PCM_Decoder Luokan metodit: command: käsittelee tcl-laajennukselta tulevat komennot stats: kirjoittaa tilastotiedot merkkijonoksi consume_samples: kutsuu adapt() ja sen jälkeen työntää tavaran mikserille adapt: synkronointi nykyiseen lähettäjään ------------------------------------------------------------------ Luokka: PCM_Decoder Kuvaus: Kantaluokka erilaisille PCM-äänidekoodereille Kantaluokka: Decoder Johdetut luokat: ADPCMDecoder, GSMDecoder, LPCDecoder Luokan metodit: recv: (virtuaalinen) ------------------------------------------------------------------ Luokka: ADPCMDecoder Kuvaus: Adaptive PCM dekooderi Kantaluokka: PCM_Decoder Johdetut luokat: - Luokan metodit: recv: kutsuu itse dekooderia adpcm_decoder() ja sen jälkeen consume_samples() ------------------------------------------------------------------ Luokka: Timer (puhdas virtuaaliluokka) Kuvaus: Tarjoaa metodin msched, jonka avulla johdetut luokat voivat pyytää Tcl-tulkkia kutsumaan johdetun luokan timeout() metodia halutun ajan päästä, aika millisekunneissa Kantaluokat: - Johdetut luokat: Clock, Controller, ReportTimer, Transmitter Luokan metodit: msched: kertoo Tcl-tulkille, että sen on kutsuttava timeout() metodia halutun ajan päästä, toteutus Tk_CreateTimerHandler kirjastofuktiolla dispatch: Tcl kutsuu tätä, joka puolestaan kutsuu johdetun luokan timeout() metodia cancel: peruuttaa tehdyn keskeytyspyynnön, jos aika kulunut ja metodia jo ehditty kutsua, ei tee mitään usched, ssched: sama kuin msched, mutta argumentti mikrosekunneissa ja sekunneissa vastaavasti gettimeofday: palauttaa ajan mikrosekunneissa vuoden 1970 alusta lukien double tyyppisenä ------------------------------------------------------------------ Luokka: AudioHandler (puhdas virtuaaliluokka) Kuvaus: Kantaluokat: - Johdetut luokat: Controller Luokan metodit: audio_handle: puhtaasti virtuaalinen ------------------------------------------------------------------ Luokka: Observable Kuvaus: Kantaluokat: - Johdetut luokat: Audio Luokan metodit: attach: detach: notify: ------------------------------------------------------------------ Luokka: Observer Kuvaus: Kantaluokat: - Johdetut luokat: Controller Luokan metodit: update: disconnect: ------------------------------------------------------------------ Luokka: MediaTimer Kuvaus: Hoitaa paria aikaleimaa Kantaluokat: - Johdetut luokat: Controller Luokan metodit: media_ts: oletustoteutus median aikaleimalle, johdetussa luokassa määritelty uudelleen ref_ts: oletustoteutus referenssiaikaleimalle, johdetussa luokassa määritelty uudelleen ------------------------------------------------------------------ Luokka: Controller Kuvaus: Ohjaa SampleStream luokan olioita Kantaluokat: TclObject, Observer, MediaTimer, AudioHandler, Timer Johdetut luokat: HDController Luokan metodit: update: pyytää keskeytystä Tcl:ltä 20 ms:n päästä, jos audiolaite ei ole avoinna active: palauttaa toden, jos audiolaite on avoinna mix_from_net: dekooderit kutsuvat tätä purettuaan paketin, tämä puolestaan kutsuu verkkoon liittyvän SampleStreamin metodia Mix maxdel: palauttaa paikalliseen SampleStreamiin liittyvän suurimman näytekoon media_ts: palauttaa paikalliseen SampleStreamiin liittyvän aikaleiman ref_ts: palauttaa aikaleiman referenssiarvon timeout: ylläpitää mahdollisimman tarkkaa aikaa tsec_ ja tusec_ muuttujissa, käytetään siinä tapauksessa, jos emme saa ajastusta avoimelta audiolaitteelta command: käsittelee tcl-laajennukselta tulevat komennot audio_handle: kutsuu metodeita DoAudio ja DoTimer DoAudio: äänen toiston ja tallennuksen hoito korkealla tasolla DoTimer: siirtyy seuraavaan frameen mixaudio: vielä korkean tason äänenkäsittelyä Output: äänen lähetys verkkoon, kutsuu send_block metodia send_block: lähettää samplet enkooderille ------------------------------------------------------------------ Luokka: SampleStream Kuvaus: tämän luokan metodeilla tehdään kaikenlaisia miksauksia ym. Kantaluokat: - Johdetut luokat: - Luokan metodit: Mix: Advance: Compute: ... ------------------------------------------------------------------ Luokka: Transmitter Kuvaus: Pakettien lähetyksen ajoitus ja statistiikan ylläpito Kantaluokat: TclObject, Timer Johdetut luokat: SessionManager Luokan metodit: ... ------------------------------------------------------------------ Luokka: SessionManager (lähes sama kuin vic:ssä) Kuvaus: RTCP:n käsittely ym Kantaluokat: Transmitter Johdetut luokat: AudioSessionManager, VideoSessionManager Luokan metodit: command: käsittelee tcl-laajennukselta tulevat komennot recv: send_bye: send_report: demux: check_format: puhtaasti virtuaalinen metodi transmit: paketin lähetys DataHandlerin kautta send_report: lähettää RTPv2 lähettäjä- tai vastaanottajaraportin ------------------------------------------------------------------
Ääniprosessin toteutukseen tarvitaan vatin luokkahierarkiasta kaikki muut luokat, paitsi sellaiset, jotka liittyvät vain äänen koodaukseen tai käyttöliittymän hoitamiseen. Tälläisiä luokkia ovat PCM_Encoder aliluokkineen, Site sekä TkWidget aliluokkineen.
Lisäksi tarvitan oma toteutus ylemmälle tasolle, joka vastaa kommunikoinnista pääprosessin kanssa ja koordinoi em. luokkahierarkioiden toimintaa. Rajapinta pääprosessin suuntaan on kuvattu kohdassa 5.4.
command
-nimistä
metodia, joka toteuttaa Tcl:n pyytämät palvelut.
Kanavan hakuun käytetään sdr:stä saatavaa valmista koodia. Sdr:stä tullaan käyttämään ainostaan niitä funktioita, jotka liittyvät multicast-lähetysten kuvausdatan hallintaan, eli ne funktiot, jotka parsivat multicast liikenteesta seuraavat tiedot: mistä lähetys tulee, minkälainen lähetys on kyseessä, koska lähetys alkaa ja loppuu, sekä lisäinformaatiot kuten sähköpostiosoitteet tai url-tieto.
Sdr käyttää istuntojen (session) tallentamiseen omaa "session"-tietuetta joka puolestaan sisältää tavallisia linkitettyjä listoja (struct lent, struct tent, struct media). Lisäksi nopeaa hakua varten on määritelty yksinkertainen hajautustaulu, jonne on varastoitu osoittimet voimassa oleviin istuntoihin.
Session-tietueen jäsenmuuttujat sisältävät kaiken olennaisen tiedon siitä mitä istunnon esittämiseen tarvitaan. Alla on on esittetty session-tietueen rakenne.
struct session { unsigned int aid; /* hajautustaulun avain */ char *username; /* kuka hoitaa tätä lähetystä */ struct in_addr orighost; /* mistä lähetys tulee */ unsigned int sessid; /* istunnon tunnusnumero */ unsigned int version; /* mikä protkollaversio sdr istunnosta on käytössä */ char *sname; /* istunnon nimi */ char *desc; /* istunnon kuvaus */ char *uri; int no_of_emails; /* montako sähköpostiosoitetta */ struct lent *email; /* sähköpostiosoitteiden lista */ int no_of_phones; /* montako puhelinumeroa */ struct lent *phone; /* puhelinumeroiden lista */ unsigned int starttime; /* koska istunto alkaa */ unsigned int endtime; /* koska istunto loppuu */ int no_of_times; /* montako istunnon lähetysaikaa */ struct tent *time; /* lähetysaikojen lista */ int no_of_attrs; /* montako atribuuttia */ struct lent *attr; /* atribuuttilista */ int no_of_media; /* motako mediaa on käytössä */ struct media *media; /* medialista */ };
Sdr:n käyttämiä tavallisia linkittetyjä listoja (data ja next jäsen) ei ole selitetty tarkemmin. Alla on kuitenkin esittetty media, joka on mielenkiintoisempi tapaus.
struct media { struct in_addr addr; /* lähetysosoite */ unsigned char ttl; /* kuinka monen reitittemen läpi lähetys pääsee - "time to live" arvo */ char *media; /* median nimi */ unsigned int port; /* lähetysportti */ char *proto; /* lähetysprotokolla */ char *fmt; /* lähetysformaatti */ int no_of_attrs; struct lent *attr; struct media *next; /* linkki seuraavaan mediaan */ };
Sdr lähdekoodistä käytetään ainostaan server_parser.c tiedoston sisältämiä funktioita. Funktiot ovat kuvattu alla.
Käyttöliittymän modulit toteutetaan siten, että Tcl:llä toteutetaan ainoastaan käyttöliittymän komponentit ja joitain aivan yksinkertaisia toimintoja. Useimpien toimintojen toteutus tehdään C++ -kielellä ja toteutusfunktioita ja -metodeja kutsutaan Tcl-ohjelmasta käsin, kuten Tcl-C++ -liittymästä on kerrottu.
C++ -toteutus on jo suurelta osin valmiina, sillä käytämme hyväksemme in ohjelmien vic, vat ja sdr funktioita ja metodeja.
Kuvan käsittely hoidetaan käyttöliittymän kanssa samassa prosessissa. Kuvan käsittelyssä käytetään vicin tarjoamia valmiita luokkia. Näiden luokkien toimintaa ohjataan käyttöliittymästä käsin, siten että, luokan command jäsenfunktiolle välitetään toiminnallisia käskyjä, jotka vaihtelevat statistiikkatietojen hausta kuvaformaatin valintaan. Erilaiset käskyt on kuvattu kappaleessa 4.1.1, jokaisen command funktion kuvauksen yhteydessä.
Kuvan käsittelyyn ei tarvitse lisätä mitään uutta funktionaalisuutta. Tämän vuoksi tässä kappaleessa on selittetty vain kuvan käsittelyyn liittyvä moduli-jako ja se mitä luokkia käytetään modulien toteuttamiseen. Kuvan siirtyminen datavirrasta monitorille tapahtuu seuraavien modulien varassa.
Rtp-protokollan käsittelyyn käytetään VideoSessionManager-luokan
funktionaalisuutta.
Raan datavirran purkua videokuvaksi avittaa Decoder-luokasta
periytävät luokat.
Kuva näyttölaitteelle saadan Render-luokasta periytyvien
luokkien avulla.
Äänen käsittely hoidetaan omassa prosessissa ilman käyttöliittymää. Tämä vähentää Internet-TV:n resurssitarpeita jonkin verran nykyiseen toteutukseen verrattuna, jossa on käytettävä yhteensä kolmea itsenäistä prosessia joista jokaisella on oma käyttöliittymä.
Prosessi jakautuu moduleihin seuraavasti:
Prosessin käynistyttyä se avaa socketin ja jää odottamaan pääprosessin antamia komentoja. Kun se on saanut tarvittavat tiedot ja komennon liittyä kanavalle, prosessi avaa tarvittavat laitteet ja soketit sekä siirtyy silmukkaan, jossa luetaan dataa verkosta, dekoodataan paketit, toistetaan purettu äänidata audiolaitteelle, päivitetään RTP tilatietoa, lähetetään RTP receiver report paketteja ja tarkistetaan mahdolliset uudet komennot pääprosessilta.
Työaseman audio-laitteen käsittely tapahtuu luokan Audio aliluokkien avulla. Verkkoliikenteen (RTP ja dekoodaus) hoitaa PacketHandler luokka. PacketHandler tarvitsee avuksi kuitenkin koko joukon muitakin luokkia kuin omat aliluokkansa.
Ääniprosessin osalta ainoat selkeät rajapinnat muodostuvat aivan matalantason dekooderien ja muun luokkahierarkian välille sekä prosessien väliseen kommunikointiin. Rajapinta dekoodereihin päin on toteutettu vatissa yksinkertaisen funktiokutsujen avulla, eikä tämä rajapinta Internet-TV:ssä muutu. Tätä rajapintaa ei siksi ole tarkemmin kuvattu. Rajapinta (protokolla) pääprosessin suuntaan on kuvattu seuraavassa kohdassa.
Protokollan tulee välittää pääprosessilta (p1) ääniprosessille (p2) ainakin seuraavia tietoja:
Lisäksi ääniprosessin on tarpeen välittää pääprosessille tieto äänen vastaanoton keskeytymisestä tai äänen puuttumisesta kokonaan tai mahdollisista muista virhetilanteista.
p1:n käynnistäessä p2:n, p1 antaa p2:n komentoriville merkkijonomuotoisen numeroaarvon, joka kertoo sen tcp-portin, jossa p1 odottaa p2:n yhteydenottoa. Kun p2 on käynnistynyt ja suorittanut tarpeelliset alustustoimenpiteet, se avaa yhteyden localhostin porttiin, jonka se sai argumenttina käynnistyessään.
Viestit p1 --> p2 ovat muotoa avain=arvo. Tässä avain kertoo haluttavan parametrin ja arvo tälle parametrille annettavan arvon. Jokainen tälläinen avain-arvo pari päättyy NULL merkkiin. Seuraavassa taulukossa on kuvattu tarvittavat avaimet ja niihin liittyvät arvot.
avain | arvo | merkitys |
---|---|---|
address | ip-numero merkkijonona | kertoo multicast-ryhmän osoitteen, jolle halutaan liittyä |
port | numero merkkijonona | kertoo tarvittavan porttinumeron (tämä on aina parillinen) |
proto | protokolla merkkijonona | Kertoo kanavalla käytettävän protokollan. Mahdollisia arvoja ovat pcm, pcm2, pcm4, dvi, dvi2, dvi4, gsm, lpc |
volume | äänenvoimakkuus arvona 0 - 100 | äänenvoimakkuuden säätö |
join | ei mitään | aloita äänen vastaanotto ja toisto |
leave | ei mitään | lopeta äänen vastaanotto ja toisto |
käyttäjän sähköpostiosoite | RTCP protokollaa varten |
p2 välittää p1:lle viestejä vain erilaisista virhetilanteista. Viestit noudattavat samaa formaattia kuin edellä.
avain | arvo | merkitys |
---|---|---|
error | virheilmoitus merkkijonona | mahdollisia virheilmoituksia ovat no-stream, no-device, no-params, poor-quality |
Kanavien haku on selkeästi oma modulinsa. Kanavan hakuun käytetään valmista koodia joka saadaan sdr:n lähdekoodista. Lähdekoodista otettavat osat ovat kuvattu tarkemmin kappaleessa 4.4.
Koska vicin ja vatin koodi on c++:lla toteuttu ja vastaavasti sdr:n koodi on ansi-c:tä, niin sdr:sta saatava koodi muutetaan yhdeksi c++-luokaksi, SdrSessioniksi, jota sitten käytetään tarpeen mukaan hyväksi.
Seuraavassa esitetään SdrSessionin sisältö. Huomaa, että jäsen funktioiden toiminta kuvataan tarkemmin kappaleessa 4.4.
class SdrSession : public TclObject { // tähän session-tietueen jäsenet. katso 4.4 SdrSession(); // sama kuin init_session, katso 4.4 ~SdrSession(); // sama kuin free_session, katso 4.4 ParseSession(char*); // sama kuin parse_session, katso 4.4 command(int, char** argv); };Luokan jäsenfunktio command tarjoaa tiedonvälitysyhteyden SdrSession-olion ja tcl-pohjaisen käyttöliittymän välille. Command käsittelee seuraavaa optiota: fetch_sessions. Jos optio on fetch_sessions niin silloin kaikkien voimassa olevat istuntojen tiedot välitetään eteenpäin.