MediaManager.java
Upload User: liulanlin
Upload Date: 2017-12-08
Package Size: 1274k
Code Size: 27k
Category:

VOIP program

Development Platform:

Java

  1. /*
  2.  * MediaManager.java
  3.  *
  4.  * Created on December 2, 2003, 8:56 AM
  5.  */
  6. package gov.nist.applet.phone.media;
  7. import javax.sdp.SessionDescription;
  8. import javax.sdp.SdpFactory;
  9. import javax.sdp.SdpException;
  10. import javax.sdp.SdpParseException;
  11. import javax.sdp.Origin;
  12. import javax.sdp.Connection;
  13. import javax.sdp.SdpConstants;
  14. import javax.sdp.MediaDescription;
  15. import javax.sdp.Media;
  16. import javax.media.*;
  17. import javax.media.protocol.*;
  18. import javax.media.protocol.DataSource;
  19. import javax.media.format.*;
  20. import javax.media.control.TrackControl;
  21. import gov.nist.applet.phone.ua.MessageListener;
  22. import gov.nist.applet.phone.media.receiver.Receiver;
  23. import gov.nist.applet.phone.media.transmitter.Transmit;
  24. import gov.nist.applet.phone.media.transmitter.StateListener;
  25. import java.util.List;
  26. import java.util.Iterator;
  27. import java.util.Vector;
  28. import java.util.Random;
  29. import java.io.IOException;
  30. /**
  31.  * This class will handle the media part of a call
  32.  * Opening the receiver and transmitter, close them,...
  33.  * 
  34.  * @author Jean Deruelle <jean.deruelle@nist.gov>
  35.  *
  36.  * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
  37.  */
  38. public class MediaManager {
  39. //Media transmitter
  40. private Transmit transmit;
  41. //Media receiver
  42. private Receiver receiver;
  43. //Codec supported by the user agent
  44. public static List audioCodecSupportedList = null;
  45. public static List videoCodecSupportedList = null;
  46. //Remote Address to connect to
  47. private String remoteAddress;
  48. //Ports chosen
  49. private int remoteAudioPort;
  50. private int localAudioPort = -1;
  51. private int remoteVideoPort;
  52. private int localVideoPort = -1;
  53. //Codecs chosen
  54. private String negotiatedAudioCodec;
  55. private String negotiatedVideoCodec;
  56. //SdpFactory to create or parse Sdp Content 
  57. private SdpFactory sdpFactory;
  58. //callListener
  59. private MessageListener callListener;
  60. //flag to know if the session has been started
  61. private boolean started;
  62. //flag to know if the media session is going through the proxy
  63. private boolean proxyEnabled;
  64. /** 
  65.  * Creates a new instance of MediaManager 
  66.  * @param callListener - the sipListener of the application
  67.  */
  68. public MediaManager(MessageListener callListener) {
  69. sdpFactory = SdpFactory.getInstance();
  70. this.callListener = callListener;
  71. started = false;
  72. proxyEnabled = false;
  73. }
  74. /**
  75.  * get the supported audio codecs in the sdp format
  76.  * @return array of the audio supported codecs
  77.  */
  78. public static String[] getSdpAudioSupportedCodecs() {
  79. Vector sdpSupportedCodecsList = new Vector();
  80. for (int i = 0; i < audioCodecSupportedList.size(); i++) {
  81. String sdpFormat =
  82. findCorrespondingSdpFormat(
  83. ((Format) audioCodecSupportedList.get(i)).getEncoding());
  84. boolean redundant = false;
  85. for (int j = 0; j < sdpSupportedCodecsList.size(); j++) {
  86. if (sdpFormat == null){
  87. redundant = true;
  88. break;
  89. }
  90. else if (sdpFormat
  91. .equalsIgnoreCase((String) sdpSupportedCodecsList.get(j))){
  92. redundant = true;
  93. break;
  94. }
  95. }
  96. if (!redundant)
  97. sdpSupportedCodecsList.addElement(sdpFormat);
  98. }
  99. for (int i = 0; i < sdpSupportedCodecsList.size(); i++)
  100. System.out.println(sdpSupportedCodecsList.get(i));
  101. return (String[]) sdpSupportedCodecsList.toArray(
  102. new String[sdpSupportedCodecsList.size()]);
  103. }
  104. /**
  105.  * get the supported video codecs in the sdp format
  106.  * @return array of the video supported codecs
  107.  */
  108. public static String[] getSdpVideoSupportedCodecs() {
  109. Vector sdpSupportedCodecsList = new Vector();
  110. for (int i = 0; i < videoCodecSupportedList.size(); i++) {
  111. String sdpFormat =
  112. findCorrespondingSdpFormat(
  113. ((Format) videoCodecSupportedList.get(i)).getEncoding());
  114. boolean redundant = false;
  115. for (int j = 0; j < sdpSupportedCodecsList.size(); j++) {
  116. if (sdpFormat == null){
  117. redundant = true;
  118. break;
  119. }
  120. else if (sdpFormat
  121. .equalsIgnoreCase((String) sdpSupportedCodecsList.get(j))){
  122. redundant = true;
  123. break;
  124. }
  125. }
  126. if (!redundant)
  127. sdpSupportedCodecsList.addElement(sdpFormat);
  128. }
  129. return (String[]) sdpSupportedCodecsList.toArray(
  130. new String[sdpSupportedCodecsList.size()]);
  131. }
  132. /**
  133.  * Detects the supported codecs of the user agent depending of 
  134.  * the devices connected to the computer
  135.  */
  136. public static void detectSupportedCodecs() {
  137. audioCodecSupportedList = new Vector();
  138. videoCodecSupportedList = new Vector();
  139. MediaLocator audioLocator = null;
  140. MediaLocator videoLocator = null;
  141. CaptureDeviceInfo videoCDI = null;
  142. CaptureDeviceInfo audioCDI = null;
  143. Vector captureDevices = null;
  144. captureDevices = CaptureDeviceManager.getDeviceList(null);
  145. System.out.println(
  146. "- number of capture devices: " + captureDevices.size());
  147. CaptureDeviceInfo cdi = null;
  148. for (int i = 0; i < captureDevices.size(); i++) {
  149. cdi = (CaptureDeviceInfo) captureDevices.elementAt(i);
  150. System.out.println(
  151. "    - name of the capture device: " + cdi.getName());
  152. Format[] formatArray = cdi.getFormats();
  153. for (int j = 0; j < formatArray.length; j++) {
  154. Format format = formatArray[j];
  155. if (format instanceof VideoFormat) {
  156. System.out.println(
  157. "         - format accepted by this VIDEO device: "
  158. + format.toString().trim());
  159. if (videoCDI == null) {
  160. videoCDI = cdi;
  161. }
  162. } else if (format instanceof AudioFormat) {
  163. System.out.println(
  164. "         - format accepted by this AUDIO device: "
  165. + format.toString().trim());
  166. if (audioCDI == null) {
  167. audioCDI = cdi;
  168. }
  169. } else
  170. System.out.println("         - format of type UNKNOWN");
  171. }
  172. }
  173. if (videoCDI != null)
  174. videoLocator = videoCDI.getLocator();
  175. if (audioCDI != null)
  176. audioLocator = audioCDI.getLocator();
  177. DataSource audioDS = null;
  178. DataSource videoDS = null;
  179. DataSource mergeDS = null;
  180. StateListener stateListener = new StateListener();
  181. //create the DataSource
  182. //it can be a 'video' DataSource, an 'audio' DataSource
  183. //or a combination of audio and video by merging both
  184. if (videoLocator == null && audioLocator == null)
  185. return;
  186. if (audioLocator != null) {
  187. try {
  188. //create the 'audio' DataSource
  189. audioDS = javax.media.Manager.createDataSource(audioLocator);
  190. } catch (Exception e) {
  191. System.out.println(
  192. "-> Couldn't connect to audio capture device");
  193. }
  194. }
  195. if (videoLocator != null) {
  196. try {
  197. //create the 'video' DataSource
  198. videoDS = javax.media.Manager.createDataSource(videoLocator);
  199. } catch (Exception e) {
  200. System.out.println(
  201. "-> Couldn't connect to video capture device");
  202. }
  203. }
  204. Processor processor = null;
  205. if (videoDS != null && audioDS != null) {
  206. try {
  207. //create the 'audio' and 'video' DataSource
  208. mergeDS =
  209. javax.media.Manager.createMergingDataSource(
  210. new DataSource[] { audioDS, videoDS });
  211. } catch (Exception e) {
  212. System.out.println(
  213. "-> Couldn't connect to audio or video capture device");
  214. }
  215. try {
  216. //Create the processor from the merging DataSource
  217. processor = javax.media.Manager.createProcessor(mergeDS);
  218. } catch (NoProcessorException npe) {
  219. npe.printStackTrace();
  220. return;
  221. } catch (IOException ioe) {
  222. ioe.printStackTrace();
  223. return;
  224. }
  225. }
  226. //if the processor has not been created from the merging DataSource
  227. if (processor == null) {
  228. try {
  229. if (audioDS != null)
  230. //Create the processor from the 'audio' DataSource
  231. processor = javax.media.Manager.createProcessor(audioDS);
  232. else
  233. //Create the processor from the 'video' DataSource
  234. processor = javax.media.Manager.createProcessor(videoDS);
  235. } catch (NoProcessorException npe) {
  236. npe.printStackTrace();
  237. return;
  238. } catch (IOException ioe) {
  239. ioe.printStackTrace();
  240. return;
  241. }
  242. }
  243. // Wait for it to configure
  244. boolean result =
  245. stateListener.waitForState(processor, Processor.Configured);
  246. if (result == false) {
  247. System.out.println("Couldn't configure processor");
  248. return;
  249. }
  250. // Get the tracks from the processor
  251. TrackControl[] tracks = processor.getTrackControls();
  252. // Do we have atleast one track?
  253. if (tracks == null || tracks.length < 1) {
  254. System.out.println("Couldn't find tracks in processor");
  255. return;
  256. }
  257. // Set the output content descriptor to RAW_RTP
  258. // This will limit the supported formats reported from
  259. // Track.getSupportedFormats to only valid RTP formats.
  260. ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
  261. processor.setContentDescriptor(cd);
  262. Format supported[];
  263. Format chosen = null;
  264. boolean atLeastOneTrack = false;
  265. // Program the tracks.
  266. for (int i = 0; i < tracks.length; i++) {
  267. Format format = tracks[i].getFormat();
  268. if (tracks[i].isEnabled()) {
  269. supported = tracks[i].getSupportedFormats();
  270. // We've set the output content to the RAW_RTP.
  271. // So all the supported formats should work with RTP.            
  272. if (supported.length > 0) {
  273. for (int j = 0; j < supported.length; j++) {
  274. System.out.println(
  275. "Supported format : "
  276. + supported[j].toString().toLowerCase());
  277. //Add to the list of video supported codec
  278. if (supported[j] instanceof VideoFormat) {
  279. videoCodecSupportedList.add(supported[j]);
  280. }
  281. //Add to the list of audio supported codec
  282. else {
  283. audioCodecSupportedList.add(supported[j]);
  284. }
  285. }
  286. }
  287. }
  288. }
  289. processor.stop();
  290. processor.close();
  291. }
  292. /**
  293.  * Start the media Session i.e. transmitting and receiving RTP stream
  294.  * TODO : handle the sendonly, recvonly, sendrcv attributes of the SDP session
  295.  */
  296. public void startMediaSession(boolean transmitFirst) {
  297. if (!started) {
  298. startReceiving();
  299. startTransmitting();
  300. started = true;
  301. }
  302. }
  303. /**
  304.  * Stop the media Session i.e. transmitting and receiving RTP stream
  305.  * TODO : handle the sendonly, recvonly, sendrcv attributes of the SDP session
  306.  */
  307. public void stopMediaSession() {
  308. stopReceiving();
  309. stopTransmitting();
  310. started = false;
  311. }
  312. /**
  313.  * Start receiving RTP stream
  314.  */
  315. protected void startReceiving() {
  316. gov.nist.applet.phone.media.util.SessionDescription sessionDescription =
  317. new gov.nist.applet.phone.media.util.SessionDescription();
  318. sessionDescription.setAddress(remoteAddress);
  319. sessionDescription.setDestinationPort(remoteAudioPort);
  320. sessionDescription.setLocalPort(localAudioPort);
  321. sessionDescription.setTransportProtocol("udp");
  322. sessionDescription.setAudioFormat(negotiatedAudioCodec);
  323. sessionDescription.setVideoFormat(negotiatedVideoCodec);
  324. receiver = new Receiver(sessionDescription, transmit);
  325. receiver.receive(callListener.getConfiguration().contactIPAddress);
  326. }
  327. /**
  328.  * start transmitting RTP stream
  329.  */
  330. protected void startTransmitting() {
  331. gov.nist.applet.phone.media.util.SessionDescription sessionDescription =
  332. new gov.nist.applet.phone.media.util.SessionDescription();
  333. sessionDescription.setAddress(remoteAddress);
  334. sessionDescription.setLocalPort(remoteAudioPort);
  335. sessionDescription.setDestinationPort(remoteAudioPort);
  336. sessionDescription.setTransportProtocol("udp");
  337. /*if(mediaTransport.equalsIgnoreCase("tcp"))
  338.     sessionDescription.setAudioFormat("99");        
  339. else*/
  340. sessionDescription.setAudioFormat(negotiatedAudioCodec);
  341. sessionDescription.setVideoFormat(negotiatedVideoCodec);
  342. transmit = new Transmit(sessionDescription, receiver);
  343. // Start the media transmission
  344. String result =
  345. transmit.start(callListener.getConfiguration().contactIPAddress);
  346. System.out.println("Media Transmission started!!!");
  347. // result will be non-null if there was an error. The return
  348. // value is a String describing the possible error. Print it.
  349. if (result != null) {
  350. System.err.println("Error : " + result);
  351. //System.exit(0);
  352. }
  353. }
  354. /**
  355.  * Stop transmitting RTP stream
  356.  */
  357. protected void stopTransmitting() {
  358. if (transmit != null) {
  359. System.out.println("Media Transmitter stopped!!!");
  360. transmit.stop();
  361. }
  362. }
  363. /**
  364.  * Stop receiving RTP stream
  365.  */
  366. protected void stopReceiving() {
  367. if (transmit != null) {
  368. System.out.println("Media Receiver stopped!!!");
  369. receiver.stop();
  370. }
  371. }
  372. /**
  373.  * Extracts from the sdp all the information to initiate the media session
  374.  * @param incomingSdpBody - the sdp Body of the incoming call to negotiate the media session
  375.  */
  376. public void prepareMediaSession(String incomingSdpBody) {
  377. SessionDescription sessionDescription = null;
  378. try {
  379. sessionDescription =
  380. sdpFactory.createSessionDescription(incomingSdpBody);
  381. //Get the remote address where the user agent has to connect to
  382. Connection remoteConnection = sessionDescription.getConnection();
  383. remoteAddress = remoteConnection.getAddress();
  384. } catch (SdpParseException spe) {
  385. spe.printStackTrace();
  386. }
  387. localAudioPort = getAudioPort();
  388. localVideoPort = getVideoPort();
  389. System.out.println("Local listening audio port : " + localAudioPort);
  390. //Extract the codecs from the sdp session description
  391. List audioCodecList = extractAudioCodecs(sessionDescription);
  392. remoteAudioPort = getAudioPort(sessionDescription);
  393. //printCodecs(audioCodecList);        
  394. System.out.println("Remote listening audio port : " + remoteAudioPort);
  395. List videoCodecList = extractVideoCodecs(sessionDescription);
  396. remoteVideoPort = getVideoPort(sessionDescription);
  397. //printCodecs(videoCodecList);
  398. //System.out.println("Remote listening video port : "+remoteVideoPort);
  399. negotiatedAudioCodec = negotiateAudioCodec(audioCodecList);
  400. negotiatedVideoCodec = negotiateVideoCodec(videoCodecList);
  401. }
  402. /**
  403.  * Getting the sdp body for creating the response to an incoming call
  404.  * @param incomingSdpBody - the sdp Body of the incoming call to negotiate the media session
  405.  * @return The sdp body that will present what codec has been chosen
  406.  * and on which port every media will be received
  407.  */
  408. public Object getResponseSdpBody(String incomingSdpBody) {
  409. prepareMediaSession(incomingSdpBody);
  410. SessionDescription sessionDescription = null;
  411. try {
  412. sessionDescription =
  413. sdpFactory.createSessionDescription(incomingSdpBody);
  414. //Get the remote address where the user agent has to connect to
  415. Connection remoteConnection = sessionDescription.getConnection();
  416. remoteAddress = remoteConnection.getAddress();
  417. } catch (SdpParseException spe) {
  418. spe.printStackTrace();
  419. }
  420. //Constructing the sdp response body
  421. SessionDescription responseSessionDescription = null;
  422. try {
  423. responseSessionDescription =
  424. (SessionDescription) sessionDescription.clone();
  425. } catch (CloneNotSupportedException cnse) {
  426. cnse.printStackTrace();
  427. }
  428. try {
  429. //Connection
  430. Connection connection =
  431. sdpFactory.createConnection(
  432. callListener.getConfiguration().contactIPAddress);
  433. responseSessionDescription.setConnection(connection);
  434. //Owner
  435. long sdpSessionId=(long)(Math.random() * 1000000);
  436. Origin origin =
  437. sdpFactory.createOrigin(
  438. callListener.sipMeetingManager.getUserURI().getUser(),
  439. sdpSessionId,
  440. sdpSessionId+1369,
  441. "IN",
  442. "IP4",
  443. callListener.getConfiguration().contactIPAddress);
  444. responseSessionDescription.setOrigin(origin);
  445. } catch (SdpException se) {
  446. se.printStackTrace();
  447. }
  448. //Media Description        
  449. Vector mediaDescriptions = new Vector();
  450. if (negotiatedAudioCodec != null) {
  451. System.out.println(
  452. "Negotiated audio codec "
  453. + negotiatedAudioCodec
  454. + " on Port "
  455. + localAudioPort);
  456. MediaDescription mediaDescription =
  457. sdpFactory.createMediaDescription(
  458. "audio",
  459. localAudioPort,
  460. 1,
  461. "RTP/AVP",
  462. new String[] { negotiatedAudioCodec });
  463. mediaDescriptions.add(mediaDescription);
  464. } else {
  465. System.out.println(
  466. "No Negotiated audio codec,"
  467. + "so no audio media descriptions will be added to the sdp body");
  468. }
  469. if (negotiatedVideoCodec != null) {
  470. System.out.println(
  471. "Negotiated video codec "
  472. + negotiatedVideoCodec
  473. + " on Port "
  474. + localVideoPort);
  475. MediaDescription mediaDescription =
  476. sdpFactory.createMediaDescription(
  477. "video",
  478. localVideoPort,
  479. 1,
  480. "RTP/AVP",
  481. new String[] { negotiatedVideoCodec });
  482. mediaDescriptions.add(mediaDescription);
  483. } else {
  484. System.out.println(
  485. "No Negotiated video codec,"
  486. + "so no video media descriptions will be added to the sdp body");
  487. }
  488. try {
  489. responseSessionDescription.setMediaDescriptions(mediaDescriptions);
  490. } catch (SdpException se) {
  491. se.printStackTrace();
  492. }
  493. return responseSessionDescription;
  494. }
  495. /**
  496.  * Extracts all the audio codecs from the description of the media session of the incoming request
  497.  * @param sessionDescription - the description of the media session of the incoming request
  498.  * @return List of all the audio codecs from the description of the media session of the incoming request
  499.  */
  500. public List extractAudioCodecs(SessionDescription sessionDescription) {
  501. List audioCodecList = new Vector();
  502. Vector mediaDescriptionList = null;
  503. try {
  504. mediaDescriptionList =
  505. sessionDescription.getMediaDescriptions(true);
  506. } catch (SdpException se) {
  507. se.printStackTrace();
  508. }
  509. try {
  510. for (int i = 0; i < mediaDescriptionList.size(); i++) {
  511. MediaDescription mediaDescription =
  512. (MediaDescription) mediaDescriptionList.elementAt(i);
  513. Media media = mediaDescription.getMedia();
  514. if (media.getMediaType().equals("audio"))
  515. audioCodecList = media.getMediaFormats(true);
  516. }
  517. } catch (SdpParseException spe) {
  518. spe.printStackTrace();
  519. }
  520. return audioCodecList;
  521. }
  522. /**
  523.  * Extracts all the video codecs from the description of the media session of the incoming request
  524.  * @param sessionDescription - the description of the media session of the incoming request
  525.  * @return List of all the audio codecs from the description of the media session of the incoming request
  526.  */
  527. public List extractVideoCodecs(SessionDescription sessionDescription) {
  528. List videoCodecList = new Vector();
  529. Vector mediaDescriptionList = null;
  530. try {
  531. mediaDescriptionList =
  532. sessionDescription.getMediaDescriptions(true);
  533. } catch (SdpException se) {
  534. se.printStackTrace();
  535. }
  536. try {
  537. for (int i = 0; i < mediaDescriptionList.size(); i++) {
  538. MediaDescription mediaDescription =
  539. (MediaDescription) mediaDescriptionList.elementAt(i);
  540. Media media = mediaDescription.getMedia();
  541. if (mediaDescription.getMedia().getMediaType().equals("video"))
  542. videoCodecList = media.getMediaFormats(true);
  543. }
  544. } catch (SdpParseException spe) {
  545. spe.printStackTrace();
  546. }
  547. return videoCodecList;
  548. }
  549. /**
  550.  * Extracts the audio port from the description of the media session of the incoming request
  551.  * @param sessionDescription - the description of the media session of the incoming request
  552.  * @return the audio port on which is listening the remote user agent
  553.  */
  554. public int getAudioPort(SessionDescription sessionDescription) {
  555. Vector mediaDescriptionList = null;
  556. try {
  557. mediaDescriptionList =
  558. sessionDescription.getMediaDescriptions(true);
  559. } catch (SdpException se) {
  560. se.printStackTrace();
  561. }
  562. try {
  563. for (int i = 0; i < mediaDescriptionList.size(); i++) {
  564. MediaDescription mediaDescription =
  565. (MediaDescription) mediaDescriptionList.elementAt(i);
  566. if (mediaDescription.getMedia().getMediaType().equals("audio"))
  567. return mediaDescription.getMedia().getMediaPort();
  568. }
  569. } catch (SdpParseException spe) {
  570. spe.printStackTrace();
  571. }
  572. return -1;
  573. }
  574. /**
  575.  * Extracts the video port from the description of the media session of the incoming request
  576.  * @param sessionDescription - the description of the media session of the incoming request
  577.  * @return the video port on which is listening the remote user agent
  578.  */
  579. public int getVideoPort(SessionDescription sessionDescription) {
  580. Vector mediaDescriptionList = null;
  581. try {
  582. mediaDescriptionList =
  583. sessionDescription.getMediaDescriptions(true);
  584. } catch (SdpException se) {
  585. se.printStackTrace();
  586. }
  587. try {
  588. for (int i = 0; i < mediaDescriptionList.size(); i++) {
  589. MediaDescription mediaDescription =
  590. (MediaDescription) mediaDescriptionList.elementAt(i);
  591. if (mediaDescription.getMedia().getMediaType().equals("video"))
  592. return mediaDescription.getMedia().getMediaPort();
  593. }
  594. } catch (SdpParseException spe) {
  595. spe.printStackTrace();
  596. }
  597. return -1;
  598. }
  599. /**
  600.  * Find the best codec between our own supported codecs 
  601.  * and the remote supported codecs to initiate the media session
  602.  * Currently, take the first one to match
  603.  * @param audioCodecList - the list of the remote audio supported codecs
  604.  * @return the negotiated audio codec
  605.  */
  606. public String negotiateAudioCodec(List audioCodecList) {
  607. //Find the mapping of the jmf format to the sdp format
  608. List audioCodecSupportedSdpFormat = new Vector();
  609. Iterator it = audioCodecSupportedList.iterator();
  610. while (it.hasNext()) {
  611. String sdpCodecValue =
  612. findCorrespondingSdpFormat(((Format) it.next()).getEncoding());
  613. if (sdpCodecValue != null)
  614. audioCodecSupportedSdpFormat.add(sdpCodecValue);
  615. }
  616. //find the best codec(currently the first one which is in both list)
  617. Iterator iteratorSupportedCodec =
  618. audioCodecSupportedSdpFormat.iterator();
  619. while (iteratorSupportedCodec.hasNext()) {
  620. String supportedCodec = (String) iteratorSupportedCodec.next();
  621. Iterator iteratorRemoteCodec = audioCodecList.iterator();
  622. while (iteratorRemoteCodec.hasNext()) {
  623. String remoteCodec = iteratorRemoteCodec.next().toString();
  624. if (remoteCodec.equals(supportedCodec))
  625. return remoteCodec;
  626. }
  627. }
  628. return null;
  629. }
  630. /**
  631.  * Find the best codec between our own supported codecs 
  632.  * and the remote supported codecs to initiate the media session
  633.  * Currently, take the first one to match
  634.  * @param videoCodecList - the list of the remote video supported codecs
  635.  * @return the negotiated video codec
  636.  */
  637. public String negotiateVideoCodec(List videoCodecList) {
  638. //Find the mapping of the jmf format to the sdp format
  639. List videoCodecSupportedSdpFormat = new Vector();
  640. Iterator it = videoCodecSupportedList.iterator();
  641. while (it.hasNext()) {
  642. String sdpCodecValue =
  643. findCorrespondingSdpFormat(((Format) it.next()).getEncoding());
  644. if (sdpCodecValue != null)
  645. videoCodecSupportedSdpFormat.add(sdpCodecValue);
  646. }
  647. //find the best codec(currently the first one which is in both list)        
  648. Iterator iteratorSupportedCodec =
  649. videoCodecSupportedSdpFormat.iterator();
  650. while (iteratorSupportedCodec.hasNext()) {
  651. String supportedCodec = (String) iteratorSupportedCodec.next();
  652. Iterator iteratorRemoteCodec = videoCodecList.iterator();
  653. while (iteratorRemoteCodec.hasNext()) {
  654. String remoteCodec = iteratorRemoteCodec.next().toString();
  655. if (remoteCodec.equals(supportedCodec))
  656. return remoteCodec;
  657. }
  658. }
  659. return null;
  660. }
  661. /**
  662.  * Utility method to print the remote codecs
  663.  */
  664. public void printCodecs(List codecList) {
  665. System.out.println("List of codecs: ");
  666. Iterator it = codecList.iterator();
  667. while (it.hasNext()) {
  668. String att = it.next().toString();
  669. System.out.println(att);
  670. }
  671. }
  672. /**
  673.  * Utility method to print the supported codecs
  674.  */
  675. public void printSupportedCodecs() {
  676. System.out.println("List of supported audio codecs: ");
  677. Iterator it = audioCodecSupportedList.iterator();
  678. while (it.hasNext()) {
  679. System.out.println(((Format) it.next()).toString());
  680. }
  681. System.out.println("List of supported video codecs: ");
  682. it = videoCodecSupportedList.iterator();
  683. while (it.hasNext()) {
  684. System.out.println(((Format) it.next()).toString());
  685. }
  686. }
  687. /**
  688.  * Utility method to print the supported codecs in parameter
  689.  * @param codecList - the list of codec to print out
  690.  */
  691. public void printSupportedCodecs(List codecList) {
  692. System.out.println("List of codecs: ");
  693. Iterator it = codecList.iterator();
  694. while (it.hasNext()) {
  695. System.out.println(it.next());
  696. }
  697. }
  698. /**
  699.  * Retrieve the audio port for this media session,
  700.  * if no audio port has been allowed it will choose one and return it
  701.  * @return the audio port for this media session
  702.  */
  703. public int getAudioPort() {
  704. if (localAudioPort == -1) {
  705. localAudioPort = new Random().nextInt(8885);
  706. if (localAudioPort % 2 == 0)
  707. localAudioPort += 1024;
  708. else
  709. localAudioPort += 1025;
  710. }
  711. return localAudioPort;
  712. }
  713. /**
  714.  * Retrieve the video port for this media session,
  715.  * if no video port has been allowed it will choose one and return it
  716.  * @return the video port for this media session
  717.  */
  718. public int getVideoPort() {
  719. if (localVideoPort == -1) {
  720. localVideoPort = new Random().nextInt(8885);
  721. if (localVideoPort % 2 == 0)
  722. localVideoPort += 1024;
  723. else
  724. localVideoPort += 1025;
  725. }
  726. return localVideoPort;
  727. }
  728. /**
  729.  * Map a jmf format to a sdp format
  730.  * @param jmfFormat - the jmf Format
  731.  * @return the corresponding sdp format
  732.  */
  733. public static String findCorrespondingSdpFormat(String jmfFormat) {
  734. if (jmfFormat == null) {
  735. return null;
  736. } else if (jmfFormat.equals(AudioFormat.ULAW_RTP)) {
  737. return Integer.toString(SdpConstants.PCMU);
  738. } else if (jmfFormat.equals(AudioFormat.GSM_RTP)) {
  739. return Integer.toString(SdpConstants.GSM);
  740. } else if (jmfFormat.equals(AudioFormat.G723_RTP)) {
  741. return Integer.toString(SdpConstants.G723);
  742. } else if (jmfFormat.equals(AudioFormat.DVI_RTP)) {
  743. return Integer.toString(SdpConstants.DVI4_8000);
  744. } else if (jmfFormat.equals(AudioFormat.DVI_RTP)) {
  745. return Integer.toString(SdpConstants.DVI4_16000);
  746. } else if (jmfFormat.equals(AudioFormat.ALAW)) {
  747. return Integer.toString(SdpConstants.PCMA);
  748. } else if (jmfFormat.equals(AudioFormat.G728_RTP)) {
  749. return Integer.toString(SdpConstants.G728);
  750. } else if (jmfFormat.equals(AudioFormat.G729_RTP)) {
  751. return Integer.toString(SdpConstants.G729);
  752. } else if (jmfFormat.equals(VideoFormat.H263_RTP)) {
  753. return Integer.toString(SdpConstants.H263);
  754. } else if (jmfFormat.equals(VideoFormat.JPEG_RTP)) {
  755. return Integer.toString(SdpConstants.JPEG);
  756. } else if (jmfFormat.equals(VideoFormat.H261_RTP)) {
  757. return Integer.toString(SdpConstants.H261);
  758. } else {
  759. return null;
  760. }
  761. }
  762. /**
  763.  * Map a sdp format to a jmf format
  764.  * @param sdpFormatStr - the sdp Format
  765.  * @return the corresponding jmf format
  766.  */
  767. public static String findCorrespondingJmfFormat(String sdpFormatStr) {
  768. int sdpFormat = -1;
  769. try {
  770. sdpFormat = Integer.parseInt(sdpFormatStr);
  771. } catch (NumberFormatException ex) {
  772. return null;
  773. }
  774. switch (sdpFormat) {
  775. case SdpConstants.PCMU :
  776. return AudioFormat.ULAW_RTP;
  777. case SdpConstants.GSM :
  778. return AudioFormat.GSM_RTP;
  779. case SdpConstants.G723 :
  780. return AudioFormat.G723_RTP;
  781. case SdpConstants.DVI4_8000 :
  782. return AudioFormat.DVI_RTP;
  783. case SdpConstants.DVI4_16000 :
  784. return AudioFormat.DVI_RTP;
  785. case SdpConstants.PCMA :
  786. return AudioFormat.ALAW;
  787. case SdpConstants.G728 :
  788. return AudioFormat.G728_RTP;
  789. case SdpConstants.G729 :
  790. return AudioFormat.G729_RTP;
  791. case SdpConstants.H263 :
  792. return VideoFormat.H263_RTP;
  793. case SdpConstants.JPEG :
  794. return VideoFormat.JPEG_RTP;
  795. case SdpConstants.H261 :
  796. return VideoFormat.H261_RTP;
  797. case 99 :
  798. return "mpegaudio/rtp, 48000.0 hz, 16-bit, mono";
  799. default :
  800. return null;
  801. }
  802. }
  803. /*PCMU  javax.media.format.AudioFormat.ULAW_RTP;
  804. 1016
  805. G721
  806. GSM  javax.media.format.AudioFormat.GSM_RTP;
  807. G723 javax.media.format.AudioFormat.G723_RTP
  808. DVI4_8000           javax.media.format.AudioFormat.DVI_RTP;
  809. DVI4_16000          javax.media.format.AudioFormat.DVI_RTP;
  810. LPC
  811. PCMA javax.media.format.AudioFormat.ALAW;
  812. G722 javax.media.format.AudioFormat.ALAW;
  813. L16_2CH
  814. L16_1CH
  815. QCELP
  816. CN
  817. MPA
  818. G728 javax.media.format.AudioFormat.G728_RTP;
  819. DVI4_11025
  820. DVI4_22050
  821. G729 javax.media.format.AudioFormat.G729_RTP
  822. CN_DEPRECATED
  823. H263 javax.media.format.VideoFormat.H263_RTP
  824. CelB
  825. JPEG javax.media.format.VideoFormat.JPEG_RTP
  826. nv
  827. H261 javax.media.format.VideoFormat.H261_RTP
  828. MPV*/
  829. }