Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Devaka Cooray
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • paul wheaton
  • Henry Wong
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Tim Moores
  • Carey Brown
  • Mikalai Zaikin
Bartenders:
  • Lou Hamers
  • Piet Souris
  • Frits Walraven

RTP Streams

 
Ranch Hand
Posts: 60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Report post to moderator
This is for secured video conferencing using JMF, i m using rtp protocol to transmit audio and video data i 'm able to do this but i want the same to be done with encrytion. There is a abstract class EncryptionInfo availble at javax.media.rtp.EncryptionInfo. since it is being an abstract class i cannt instantiate it so need ur help to overcome this problem. PLEASE HELP!

import java.awt.*;
import java.io.*;
import java.net.InetAddress;
import java.util.*;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.control.QualityControl;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.rtp.rtcp.*;


public class AVTransmitter implements ReceiveStreamListener, RemoteListener,
ControllerListener {

// Input MediaLocator
// Can be a file or http or capture source
private MediaLocator locator;
private String ipAddress;
private int portBase;

private Processor processor = null;
private RTPManager rtpMgrs[];
private int localPorts[];
private DataSource dataOutput = null;
private int local_data_port;

private Tx tx;

public AVTransmitter( Tx tx, int data_port) {
this.tx= tx;

local_data_port= data_port;
}

/**
* Starts the transmission. Returns null if transmission started ok.
* Otherwise it returns a string with the reason why the setup failed.
*/
public synchronized String start( String filename, Vector targets) {
String result;

locator= new MediaLocator( filename);

// Create a processor for the specified media locator
// and program it to output JPEG/RTP
result = createProcessor();
if (result != null) {
return result;
}

// Create an RTP session to transmit the output of the
// processor to the specified IP address and port no.
result = createTransmitter( targets);

if (result != null) {
processor.close();
processor = null;

return result;
}

// Start the transmission
processor.start();

return null;
}

/**
* Use the RTPManager API to create sessions for each media
* track of the processor.
*/
private String createTransmitter( Vector targets) {
// Cheated. Should have checked the type.
PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
PushBufferStream pbss[] = pbds.getStreams();

rtpMgrs = new RTPManager[pbss.length];
localPorts = new int[ pbss.length];
SessionAddress localAddr, destAddr;
InetAddress ipAddr;
SendStream sendStream;
int port;
SourceDescription srcDesList[];

for (int i = 0; i < pbss.length; i++) {
// for (int i = 0; i < 1; i++) {
try {
rtpMgrs[i] = RTPManager.newInstance();

port = local_data_port + 2*i;

localPorts[ i]= port;

localAddr = new SessionAddress( InetAddress.getLocalHost(),
port);

rtpMgrs[i].initialize( localAddr);
rtpMgrs[i].addReceiveStreamListener(this);
rtpMgrs[i].addRemoteListener(this);

for( int k= 0; k < targets.size(); k++) {
Target target= (Target) targets.elementAt( k);

int targetPort= new Integer( target.port).intValue();

addTarget( localPorts[ i], rtpMgrs[ i], target.ip, targetPort + 2*i);
}

sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
sendStream.start();
} catch (Exception e) {
e.printStackTrace();

return e.getMessage();
}
}

return null;
}

public void addTarget( String ip, String port) {
for (int i= 0; i < rtpMgrs.length; i++) {
int targetPort= new Integer( port).intValue();

addTarget( localPorts[ i], rtpMgrs[ i], ip, targetPort + 2*i);
}
}

public void addTarget( int localPort, RTPManager mgr, String ip, int port) {
try {
SessionAddress addr= new SessionAddress( InetAddress.getByName( ip),
new Integer( port).intValue());

mgr.addTarget( addr);

tx.addTargetToList( localPort + "", ip, port + "");
} catch( Exception e) {
e.printStackTrace();
}
}

public void removeTarget( String ip, String port) {
try {
SessionAddress addr= new SessionAddress( InetAddress.getByName( ip),
new Integer( port).intValue());

for (int i= 0; i < rtpMgrs.length; i++) {
rtpMgrs[ i].removeTarget( addr, "target removed from transmitter.");
}
} catch( Exception e) {
e.printStackTrace();
}
}

boolean looping= true;

public void controllerUpdate( ControllerEvent ce) {
System.out.println( ce);
if( ce instanceof DurationUpdateEvent) {
Time duration= ((DurationUpdateEvent) ce).getDuration();

System.out.println( "duration: " + duration.getSeconds());
} else if( ce instanceof EndOfMediaEvent) {
System.out.println( "END OF MEDIA - looping=" + looping);
if( looping) {
processor.setMediaTime( new Time( 0));
processor.start();
}
}
}

public void setLooping( boolean flag) {
looping= flag;
}

public void update( ReceiveStreamEvent event) {
String timestamp= getTimestamp();

StringBuffer sb= new StringBuffer();

if( event instanceof InactiveReceiveStreamEvent) {
sb.append( timestamp + " Inactive Receive Stream");
} else if( event instanceof ByeEvent) {
sb.append( timestamp + " Bye");
} else {
System.out.println( "ReceiveStreamEvent: "+ event);
}

tx.rtcpReport( sb.toString());
}

public void update( RemoteEvent event) {
String timestamp= getTimestamp();

if( event instanceof ReceiverReportEvent) {
ReceiverReport rr= ((ReceiverReportEvent) event).getReport();

StringBuffer sb= new StringBuffer();

sb.append( timestamp + " RR");

if( rr != null) {
Participant participant= rr.getParticipant();

if( participant != null) {
sb.append( " from " + participant.getCNAME());
sb.append( " ssrc=" + rr.getSSRC());
} else {
sb.append( " ssrc=" + rr.getSSRC());
}

tx.rtcpReport( sb.toString());
}
} else {
System.out.println( "RemoteEvent: " + event);
}
}

private String getTimestamp() {
String timestamp;

Calendar calendar= Calendar.getInstance();

int hour= calendar.get( Calendar.HOUR_OF_DAY);

String hourStr= formatTime( hour);

int minute= calendar.get( Calendar.MINUTE);

String minuteStr= formatTime( minute);

int second= calendar.get( Calendar.SECOND);

String secondStr= formatTime( second);

timestamp= hourStr + ":" + minuteStr + ":" + secondStr;

return timestamp;
}

private String formatTime( int time) {
String timeStr;

if( time < 10) {
timeStr= "0" + time;
} else {
timeStr= "" + time;
}

return timeStr;
}

/**
* Stops the transmission if already started
*/
public void stop() {
synchronized (this) {
if (processor != null) {
processor.stop();
processor.close();
processor = null;

for (int i= 0; i < rtpMgrs.length; i++) {
rtpMgrs[ i].removeTargets( "Session ended.");
rtpMgrs[ i].dispose();
}
}
}
}


public String createProcessor() {
if (locator == null) {
return "Locator is null";
}

DataSource ds;
DataSource clone;

try {
ds = javax.media.Manager.createDataSource(locator);
} catch (Exception e) {
return "Couldn't create DataSource";
}

// Try to create a processor to handle the input media locator
try {
processor = javax.media.Manager.createProcessor(ds);
processor.addControllerListener( this);
} catch (NoProcessorException npe) {
return "Couldn't create processor";
} catch (IOException ioe) {
return "IOException creating processor";
}

// Wait for it to configure
boolean result = waitForState(processor, Processor.Configured);
if (result == false)
return "Couldn't configure processor";

// Get the tracks from the processor
TrackControl [] tracks = processor.getTrackControls();

// Do we have atleast one track?
if (tracks == null || tracks.length < 1)
return "Couldn't find tracks in processor";

// Set the output content descriptor to RAW_RTP
// This will limit the supported formats reported from
// Track.getSupportedFormats to only valid RTP formats.
ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
processor.setContentDescriptor(cd);

Format supported[];
Format chosen;
boolean atLeastOneTrack = false;

// Program the tracks.
for (int i = 0; i < tracks.length; i++) {
Format format = tracks[i].getFormat();
if (tracks[i].isEnabled()) {

supported = tracks[i].getSupportedFormats();

// We've set the output content to the RAW_RTP.
// So all the supported formats should work with RTP.
// We'll just pick the first one.

if (supported.length > 0) {
if (supported[0] instanceof VideoFormat) {
// For video formats, we should double check the
// sizes since not all formats work in all sizes.
chosen = checkForVideoSizes(tracks[i].getFormat(),
supported[0]);
} else
chosen = supported[0];
tracks[i].setFormat(chosen);
System.err.println("Track " + i + " is set to transmit as:");
System.err.println(" " + chosen);
atLeastOneTrack = true;
} else
tracks[i].setEnabled(false);
} else
tracks[i].setEnabled(false);
}

if (!atLeastOneTrack)
return "Couldn't set any of the tracks to a valid RTP format";

// Realize the processor. This will internally create a flow
// graph and attempt to create an output datasource for JPEG/RTP
// audio frames.
result = waitForState(processor, Controller.Realized);
if (result == false)
return "Couldn't realize processor";

// Set the JPEG quality to .5.
setJPEGQuality(processor, 0.5f);

// Get the output data source of the processor
dataOutput = processor.getDataOutput();

return null;
}

static SessionAddress destAddr1, destAddr2;

/**
* For JPEG and H263, we know that they only work for particular
* sizes. So we'll perform extra checking here to make sure they
* are of the right sizes.
*/
Format checkForVideoSizes(Format original, Format supported) {

int width, height;
Dimension size = ((VideoFormat)original).getSize();
Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
Format h263Fmt = new Format(VideoFormat.H263_RTP);

if (supported.matches(jpegFmt)) {
// For JPEG, make sure width and height are divisible by 8.
width = (size.width % 8 == 0 ? size.width :
(int)(size.width / 8) * 8);
height = (size.height % 8 == 0 ? size.height :
(int)(size.height / 8) * 8);
} else if (supported.matches(h263Fmt)) {
// For H.263, we only support some specific sizes.
if (size.width < 128) {
width = 128;
height = 96;
} else if (size.width < 176) {
width = 176;
height = 144;
} else {
width = 352;
height = 288;
}
} else {
// We don't know this particular format. We'll just
// leave it alone then.
return supported;
}

return (new VideoFormat(null,
new Dimension(width, height),
Format.NOT_SPECIFIED,
null,
Format.NOT_SPECIFIED)).intersects(supported);
}


/**
* Setting the encoding quality to the specified value on the JPEG encoder.
* 0.5 is a good default.
*/
void setJPEGQuality(Player p, float val) {

Control cs[] = p.getControls();
QualityControl qc = null;
VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);

// Loop through the controls to find the Quality control for
// the JPEG encoder.
for (int i = 0; i < cs.length; i++) {

if (cs[i] instanceof QualityControl &&
cs[i] instanceof Owned) {
Object owner = ((Owned)cs[i]).getOwner();

// Check to see if the owner is a Codec.
// Then check for the output format.
if (owner instanceof Codec) {
Format fmts[] = ((Codec)owner).getSupportedOutputFormats(null);
for (int j = 0; j < fmts.length; j++) {
if (fmts[j].matches(jpegFmt)) {
qc = (QualityControl)cs[i];
qc.setQuality(val);
System.err.println("- Setting quality to " +
val + " on " + qc);
break;
}
}
}
if (qc != null)
break;
}
}
}


/****************************************************************
* Convenience methods to handle processor's state changes.
****************************************************************/

private Integer stateLock = new Integer(0);
private boolean failed = false;

Integer getStateLock() {
return stateLock;
}

void setFailed() {
failed = true;
}

private synchronized boolean waitForState(Processor p, int state) {
p.addControllerListener(new StateListener());
failed = false;

// Call the required method on the processor
if (state == Processor.Configured) {
p.configure();
} else if (state == Processor.Realized) {
p.realize();
}

// Wait until we get an event that confirms the
// success of the method, or a failure event.
// See StateListener inner class
while (p.getState() < state && !failed) {
synchronized (getStateLock()) {
try {
getStateLock().wait();
} catch (InterruptedException ie) {
return false;
}
}
}

if (failed)
return false;
else
return true;
}

/****************************************************************
* Inner Classes
****************************************************************/

class StateListener implements ControllerListener {

public void controllerUpdate(ControllerEvent ce) {
// If there was an error during configure or
// realize, the processor will be closed
if (ce instanceof ControllerClosedEvent)
setFailed();

// All controller events, send a notification
// to the waiting thread in waitForState method.
if (ce instanceof ControllerEvent) {
synchronized (getStateLock()) {
getStateLock().notifyAll();
}
}
}
}
}
 
Bartender
Posts: 9626
16
Mac OS X Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Report post to moderator
Please do not post the same question in multiple forums.
 
He baked a muffin that stole my car! And this tiny ad:
We need your help - Coderanch server fundraiser
https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
    Bookmark Topic Watch Topic
  • New Topic