JMF RTP สำหรับ ผู้ส่ง

JMF RTP Transmit 

หลังจากวุ่น ๆ กับวิธีการทำ Register กับเจ้า Asterisk อยู่นานจนสามารถ Register ได้ แต่ก็มาถึงขั้นตอนการ Invite และ เริ่มคุยกับ ขั้นตอนการ Invite ก็คล้าย ๆ กับ Register นะแหละ แต่ผมยังไม่ได้เขียน เพราะว่า เมื่อ Invite เสร็จแล้ว ก็ต้องมีการส่งข้อมูลกัน ซึ่งตรงนี้ต้องใช้ความรู้ของเรื่อง JMF และ RTP ผมก็เลย แว๊บ มาเขียนเรื่องนี้ไว้สักหน่อยกันลืมคร๊าบ...บ  :-)

 import javax.media.*;
 import javax.media.protocol.*;
 import javax.media.rtp.*;
 import java.net.*;

 import javax.media.control.*;
 import javax.media.format.*;

 public class Transmit  {
   private Processor processor;

   public Transmit( String destAddress, int destPort) {
     DataSource source = null;

        MediaLocator ml = new MediaLocator("javasound://");

        try {
            source = Manager.createDataSource(ml);
        }
        catch (Exception exc) {
            System.out.println("Error");
        }

     try {
       processor = Manager.createProcessor(source);
       processor.configure();
       while(processor.getState()<Processor.Configured) {
         try {
            Thread.sleep(10);
         }catch(Exception exc){
             System.out.println("Error");
          }
       }

            processor.setContentDescriptor(new
                ContentDescriptor(ContentDescriptor.RAW_RTP));

            TrackControl [] tracks = processor.getTrackControls();
            tracks[0].setFormat(new AudioFormat(AudioFormat.ULAW_RTP));

            processor.realize();
            while(processor.getState() < Processor.Realized)  {
                 try {
                         Thread.sleep(10);
                 }catch(Exception ex){
                    System.out.println("Error");
                 }
             }
            System.out.println("Realize completed.");
          }
            catch(Exception exc) {
                System.out.println("Create processor failed.");
          }

     DataSource output = processor.getDataOutput();
     try {
       RTPManager rtpMgr = RTPManager.newInstance();
       SessionAddress localAddr = new SessionAddress(
                   InetAddress.getLocalHost(), destPort);
       rtpMgr.initialize(localAddr);
       SessionAddress destAddr = new SessionAddress(
                   InetAddress.getByName(destAddress), destPort);
       rtpMgr.initialize(localAddr);
          rtpMgr.addTarget(destAddr);
      
       SendStream sendStream =
                      rtpMgr.createSendStream(output,0);
       sendStream.start();
       processor.start();
     }
     catch(Exception exc) {
          exc.printStackTrace();
       System.out.println("Create  transmitter failed");
    }
   }

   public static void main(String[] args) {
       new Transmit("147.127.240.91",9000);
          System.out.println("finish");
  }
 } 

code ตัวอย่างนี้ เป็นการเขียน JMF สำหรับส่งเสียงผ่านทาง RTP โดยมีหลักการทำงานคือ

  • สร้าง media Locator ซึ่งอาจจะเป็น javasound:// (microphone), file:// , vfw://  หรืออื่น ๆ
  • สร้าง Datasource (source) จาก medialocator
  • สร้าง processor เพื่อนำ datasource ที่กำหนดมาประมวลผลก่อน เราสามารถกำหนด Codec, sampling rate และตัวแปรอื่น ๆ ใน processor  จากนั้นก็สั่ง processor ให้ realize() และรอจนกว่ามันจะ realized เสร็จเรียบร้อย เพื่อเตรียมพร้อมส่งข้อมูล
  • สร้าง DataSource (output) จาก processor อีกครั้ง เพื่อพร้อมที่จะส่งข้อมูล
  • สร้าง RTPManager เพื่อ initialize และ addTarget ระหว่างผู้รับกับผู้ส่ง
  • สร้าง SessionAddress ของ ผู้รับและผู้ส่ง และเชื่อมต่อ SessionAddress ผ่าน RTPManager
  • สร้าง SendStream จาก DataSource (output) ผ่าน RTPManager แล้วก็ส่ง Stream ลงไปใน network และ start processor

ก่อนทดลอง run code นี้ อย่าลืมติดตั้ง JMF lib ก่อน ผมทดลอง code นี้ บน Ubuntu สามารถ run ได้ แต่ปรากฎว่าไม่มันไม่ยอมส่ง packet ออกไป  คาดว่าน่าจะเป็นการติดตั้ง JMF ที่ไม่สมบูรณ์ แต่ ทดลองบน Windows XP ไม่พบปัญหาใด ๆ ครับ