Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Receptia si prezentarea stream-urilor RTP

java


Receptia si prezentarea stream-urilor RTP

Player-ele si Processoarele JMF prevad mecanismele de prezentare, captura si conversie a datelor pentru stream-urile RTP.



Figura 8.25.    Fluxul datelor spre receptia RTP

Un Player separat este folosit pentru fiecare stream receptionat de managerul de sesiune. Pentru a construi un Player pentru un stream RTP se foloseste mecanismul standard Manager createPlayer. Exista doua posibilitati:

se foloseste un MediaLocator care are parametrii unei sesiuni RTP si se construieste un Player prin apelarea Manager.createPlayer(MediaLocator;

se construieste un Player pentru un anumit ReceiveStream prin obtinerea DataSource-ului din stream-ul de date si prin transmiterea lui la Manager.createPlayer(DataSource).

Daca se foloseste un MediaLocator la construirea unui Player, se poate prezenta doar primul str 848j95i eam RTP care este detectat īn sesiune. Daca se doreste rularea de stream-uri multiple īntr-o sesiune, trebuie folosita SessionManager direct si trebuie construit un Player pentru fiecare ReceiveStream.

8.8.1. Crearea unui Player pentru o sesiune RTP

Cānd se foloseste un MediaLocator la constructia unui Player pentru o sesiune RTP, Manager-ul creaza un Player pentru primul stream detectat īn sesiune. Acest Player posteaza un eveniment RealizeCompleteEvent odata ce datele au fost detectate īn sesiune.

Prin "ascultarea" pentru aparitia evenimentului RealizeCompleteEvent, se poate determina daca au sosit date si daca Player-ul este capabil sa prezinte aceste date. Odata ce Player-ul posteaza acest eveniment, se pot obtine componentele lui vizuale si de control.

Un Player poate exporta un control specific RTP, RTPControl, care furnizeaza statistici si care poate fi folosit la īnregistrarea dinamica cu SessionManager-ul.

Exemplul 8.13.    Crearea unui Player pentru o sesiune RTP

String url= "rtp://224.144.251.104:49150/audio/1";

MediaLocator mrl= new MediaLocator(url);

if (mrl == null)

// Creeaza un Player pentru sesiune RTP curenta

try catch (NoPlayerException e) catch (MalformedURLException e) catch (IOException e)

if (player != null)

}

Cānd un Player posteaza un eveniment FormatChangeEvent, indica faptul ca datele utile au suferit o modificare. Player-ele construite cu un MediaLocator proceseaza aceste modificari automat. Īn majoritatea cazurilor, aceasta procesare implica construirea unui nou Player care sa manipuleze datele īn noul format.

Aplicatiile care prezinta stream-urile RTP trebuie sa "asculte" pentru evenimente FormatChangeEvents care pot raspunde daca un nou Player este creat.

Cānd un eveniment FormatChangeEvent este postat, trebuie verificat daca controlul obiectului si componentele vizuale ale Player-ului s-au modificat. Daca da, un nou Player trebuie construit iar referintele la vechiul Player trebuie īnlocuite cu cele la noul Player.

Exemplul 8.14. "Ascultarea" pentru modificari de format RTP

public synchronized void controllerUpdate(ControllerEvent ce)

framePanel.remove(oldVisualComp);

vSize = visualComp.getPreferredSize();

vSize.width = (int)(vSize.width * defaultScale);

vSize.height = (int)(vSize.height * defaultScale);

framePanel.add(visualComp);

visualComp.setBounds(0, 0, vSize.width, vSize.height);

addPopupMenu(visualComp);

}

}

Component oldComp = controlComp;

controlComp = player.getControlPanelComponent();

if (controlComp != null)

}

}

}

}

8.8.2. Crearea unui Player RTP pentru fiecare stream receptionat

Pentru a rula toate ReceiveStream-urile dintr-o sesiune, trebuie creat un Player separat pentru fiecare stream. Cānd un nou stream este creat, managerul de sesiune posteaza un eveniment NewReceiveStreamEvent. Īn general trebuie īnregistrat ca si ReceiveStreamListener si trebuie construit cāte un Player pentru fiecare ReceiveStream. Pentru a construi un Player, trebuie obtinuta DataSource-ul din ReceiveStream si transmisa la Manager.createPlayer.

Pentru a crea un Player pentru fiecare stream receptionat īntr-o sesiune trebuie:

setata sesiune RTP:

creat un SessionManager;

apelat RTPSessionMgr addReceiveStreamListener pentru a se īnregistra ca si listener;

porneste sesiunea RTP prin apelarea RTPSessionMgr startSession;

Exemplul 8.15. Setarea unei sesiuni RTP

public SessionManager createManager(String address,

int port, int ttl, boolean listener,boolean sendlistener)

catch (SecurityException e)

// creaza Session Address local

SessionAddress localaddr = new SessionAddress();

try;

mgr.initSession(localaddr, userdesclist, 0.05, 0.25);

mgr.startSession(sessaddr,ttl,null);

} catch (Exception e)

return mgr;

}

Īn metoda ReceiveStreamListener update, trebuie "ascultat" pentru evenimentul NewReceiveStreamEvent, care indica ca un nou stream de date a fost detectat.

Cānd un eveniment NewReceiveStreamEvent     este detectat, trebuie apelata metoda getReceiveStream pentru a obtine ReceiveStream.

Trebuie obtinuta DataSource-ul RTP din ReceiveStream prin apelarea metodei getDataSource cu un Format specific RTP. Spre exemplu, codarea pentru un player audio DVI va fi DVI_RTP.

Trebuie transmits DataSource-ul la Manager.createPlayer pentru a construi un Player. Pentru ca acesta sa fie construit cu succes, plug-in-urile pentru decodare si despachetare a datelor formatate RTP trebuie sa fie disponibile.

Exemplul 8.16. "Ascultarea" pentru NewReceiveStreamEvents

public void update( ReceiveStreamEvent event)

catch (Exception e)

if (newplayer == null) return;

playerlist.addElement(newplayer);

newplayer.addControllerListener(this);

// trimite acest player spre player GUI

playerWindow = new RTPPlayerWindow( newplayer, cname);

}

}

Daca datele utile dintr-un stream dintr-o sesiune RTP se modifica, ReceiveStream posteaza un eveniment RemotePayloadChangeEvent. De obicei, cānd datele sufera modificari, Player-ul existent nu va recunoaste noul format si JMF va "arunca" o eroare daca se īncearca prezentarea datelor. Pentru a evita aceasta, ReceiveStreamListener trebuie sa urmareasca pentru evenimente RemotePayloadChangeEvents. Cānd un astfel de eveniment este detectat, trebuie:

īnchis Player-ul curent;

retrase toate listener-ele care tineau de acel Player;

creat un nou Player cu aceeasi DataSource RTP;

obtinute Componentele vizuale si de control prntru noul Player;

adaugate listener-ele necesare pentru noul Player;

Exemplul 8.17. Tratarea modificarilor datelor utile din stream

public void update(ReceiveStreamEvent event)

newplayer.addControllerListener(listener);

newplayer.realize();

// cand noul player este in starea realized , obtine

// componentele lui vizuale si de control

} catch (Exception e)

}

}

}

Buffer-ul de receptie RTP poate fi controlat prin BufferControl exportat de catre SessionManager. Acest control permite setarea a doi parametrii: lungimea buffer-ului si pragul (treshold).

Lungimea buffer-ului este marimea buffer-ului mentinut de catre receptor. Pragul este cantitatea minima de date care este stocata īn buffer īnainte de trimiterea datelor. Datele vor fi disponibile de la acest obiect cānd acest prag minim este atins. Daca datele din buffer nu ating acest prag, datele vor fi buffer-ate din nou pāna cānd pragul este atins.

Lungimea buffer-ului si valoarea de prag sunt specificate īn milisecunde. Numarul de pachete audio si de cadre video din buffer depinde de formatul streamului de la intrare. Fiecare stream de intrare mentine propriile valori implicite si maxime atāt pentru lungimea buffer-ului cāt si pentru pragul minim. Valorile implicite si maxime sunt independente de aplicatie.

Pentru a obtine BufferControl pentru o sesiune, trebuie apelata metoda getControl asupra SessionManager-ului. Se poate obtine o componenta GUI pentru un BufferControl prin apelarea getControlComponent.

8.8.3. Prezentarea stream-urilor RTP cu RTPSocket

RTP este un protocol independent de protocolul de transport folosit. Folosind RTPSocket, se pot receptiona stream-uri RTP din orice retea. Formatul socket-ului RTP este proiectat sa aiba un canal pentru date si unul de control.

Fiecare canal are un stream de intrare si unul de iesire pentru a transmite si a receptiona datele īn/din retea.

SessionManager-ul se asteapta sa primeasca pachete RTP individuale de la RTPSocket. Utilizatorii sunt responsabili de trimiterea pachetelor individuale spre RTPSocket.

Pentru a rula un stream RTP de la RTPSocket, trebuie transmis acest socket la Manager.createPlayer pentru a construi Player-ul. Alternativ, se poate construi un Player prin apelarea createPlayer(MediaLocator) si trecerea la MediaLocator cu un nou protocol care este o varianta a RTP, "rtpraw". Spre exemplu,

Manager.createPlayer(new MediaLocator("rtpraw://"));

Conform mecanismului    de creere a unui Player JMF, Manger-ul va īncerca sa construiasca DataSource-ul:

<protocol package-prefix>.media.protocol.rtpraw.DataSource

Continutul RTPSocket trebuie setat pe rtpraw. Manager-ul va incerca sa creeze un Player de tipul <content-prefix>.media.content.rptraw.Handler si va seta RTPSocket-ul pe acesta.

Nota: RTPSocket-ul creat la <protocol package-prefix> .media.protocol.rtpraw.DataSource este implementarea proprie a acestuia. Implementarea RTPSocket-ului este dependenta de protocolul de transport folosit. Clasa RTPSocket trebuie localizata la <protocol package-prefix>.media.protocol.rtpraw.DataSource iar canalele de date si control trebuie setate sa arate ca si īn Exemplul 8.18. Interfetele RTPControl pentru RTPSocket pot fi utilizate pentru a adauga informatii dinamice manager-ului de sesiune RTP.

Exemplul 8.18 implementeaza o sesiune RTP peste un Player UDP care poate receptiona pachete RTP UDP si le poate transmite unui Player sau unui manager de sesiune. Acest exemplu foloseste interfetele definite īn javax.media.rtp.RTPSocket si clasele care apartin acesteia.

Exemplul 8.18. RTPSocketPlayer

import java.io.*;

import java.net.*;

import java.util.*;

import javax.media.*;

import javax.media.format.*;

import javax.media.protocol.*;

import javax.media.rtp.*;

import javax.media.rtp.event.*;

import javax.media.rtp.rtcp.*;

public class RTPSocketPlayer implements ControllerListener catch (NoPlayerException e)

catch (IOException e)

if (player != null)

}

public synchronized void controllerUpdate(ControllerEvent ce)

}

private DatagramSocket InitSocket(String sockaddress,

int sockport)

else

return sock;

}

catch (SocketException e)

catch (UnknownHostException e)

catch (IOException e)

}

public class UDPHandler extends Thread implements

PushSourceStream, OutputDataStream

// threadul principal primeste pachete RTP din retea si transfera

// aceste date handlerului de iesire a acestui stream

public void run()

try

len = dp.getLength();

if (len > (maxsize >> 1)) maxsize = len << 1;

}

while (len >= dp.getData().length);

}catch (Exception e)

if (outputHandler != null)

}

}

public void close()

private void cleanup()

// metodele pentru PushSourceStream

public Object[] getControls()

public Object getControl(String controlName)

public ContentDescriptor getContentDescriptor()

public long getContentLength()

public boolean endOfStream()

// metoda prin care datele sunt transferate din retea spre

// managerul de sesiune

public int read(byte buffer[],

int offset,

int length)

public int getMinimumTransferSize()

public void setTransferHandler(SourceTransferHandler

transferHandler)

// metode pentru OutputDataStream folosite de managerul de

// sesiune pentru a transmite date in retea

public int write(byte[] buffer,

int offset,

int length)

catch (UnknownHostException e)

DatagramPacket dp = new DatagramPacket( buffer,

length,

addr,

myport);

try catch (IOException e)

return dp.getLength();

}

}

public static void main(String[] args)



Document Info


Accesari: 1101
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )