2010-09-26 17 views
8

बनाने में सहायता करें मैं एक स्पीक्स वीओआईपी क्लाइंट और सर्वर बनाने की कोशिश कर रहा हूं। मेरे पास मूल बातें हैं और यह यूडीपी पर स्थानीय मशीन पर ठीक काम कर रही है। मैं पोर्टेबिलिटी के लिए जेएसपेक्स का उपयोग कर रहा हूं। मैं ग्राहक और सर्वर बनाने के सुझावों की तलाश में हूं। आपके क्या विचार हैं?एक स्पीक्स वीओआईपी सर्वर और क्लाइंट

जेएसपेक्स लाइब्रेरी केवल 320 बाइट प्रति कॉल एन्कोड कर सकती है ताकि सर्वर पर भेजे गए पैकेट छोटे (मेरे मामले में ~ 244 बाइट्स) हो। क्या ग्राहक के लिए इंतजार करना बेहतर होगा जब तक कि एन्कोडेड डेटा के लगभग 1 या 2 केबी तैयार नहीं हो जाते हैं या सर्वर को पैकेट बफरिंग करने से पहले तैयार करते हैं?

इसके अलावा, डेटा बफरिंग को कार्यान्वित करने के तरीके पर कोई भी मदद अच्छी होगी।

मेरे पास जो कुछ है वह स्थानीय मशीन पर काम करता है।

ग्राहक:

public void run() { 
    int nBytesToRead = (m_inputAudioFormat.getFrameSize() * 160); 
    int nAvailable = 0; 
    byte[] abPCMData = new byte[nBytesToRead]; 
    byte[] abSpeexData = null; 
    UserSpeexPacket userSpeexPacket = new UserSpeexPacket("Xiphias3", "TheLounge", null, 0); 

    while (m_captureThread != null) { 
     nAvailable = m_line.available(); 
     if (nAvailable >= nBytesToRead) { 
      int nBytesRead = m_line.read(abPCMData, 0, nBytesToRead); 
      if (nBytesRead == -1) break; 
      if (nBytesRead < nBytesToRead) 
       Arrays.fill(abPCMData, nBytesRead, abPCMData.length, (byte) 0); 
      abSpeexData = createSpeexPacketFromPCM(abPCMData, 0, abPCMData.length); 
      //DatagramPacket packet = new DatagramPacket(abSpeexData, 0, abSpeexData.length, m_connection.getInetAddress(), m_nServerPort); 
      userSpeexPacket.setSpeexData(abSpeexData); 
      userSpeexPacket.incrementPacketNumber(); 
      DatagramPacket packet = UserSpeexPacket.userSpeexPacketToDatagramPacket(m_connection.getInetAddress(), m_connection.getPort(), userSpeexPacket); 
      try { 
       m_connection.send(packet); 
      } 
      catch(IOException iox) { 
       System.out.println("Connection to server lost: " + iox.getMessage()); 
       break; 
      } 
     } 
    } 
    closeLine(); 
    disconnect(); 
} 

public byte[] createSpeexPacketFromPCM(byte[] abPCMData, int nOffset, int nLength) 
{ 
    byte[] abEncodedData = null; 
    m_speexEncoder.processData(abPCMData, nOffset, nLength); 
    abEncodedData = new byte[m_speexEncoder.getProcessedDataByteSize()]; 
    m_speexEncoder.getProcessedData(abEncodedData, 0); 
    return abEncodedData; 
} 

सर्वर:

DatagramPacket packet = new DatagramPacket(new byte[2048], 0, 2048); 
    byte[] abPCMData = null; 
    long lPrevVolPrintTime = 0; 

    while (m_bServerRunning) { 
     try { 
      m_serverSocket.receive(packet); 
      //System.out.println("Packet size is " + packet.getData().length); 
      //System.out.println("Got packet from " + packet.getAddress().getHostAddress()); 
      //abPCMData = decodeSpeexPacket(packet.getData(), 0, packet.getLength()); 
      UserSpeexPacket usp = UserSpeexPacket.datagramPacketToUserSpeexPacket(packet); 
      abPCMData = decodeSpeexPacket(usp.getSpeexData(), 0, usp.getSpeexData().length); 
      m_srcDataLine.write(abPCMData, 0, abPCMData.length); 

      if (System.currentTimeMillis() >= (lPrevVolPrintTime + 500)) { 
       //System.out.println("Current volume: " + AudioUtil.getVolumeLevelForPCM22050Hz16Bit1Channel(abPCMData, 0, abPCMData.length)); 
       lPrevVolPrintTime = System.currentTimeMillis(); 
      } 
     } 
     catch (IOException iox) { 
      if (m_bServerRunning) { 
       System.out.println("Server socket broke: " + iox.getMessage()); 
       stopServer(); 
      } 
     } 
    } 

उत्तर

5

मैं एक ऐसी ही परियोजना पर काम कर रहा हूँ। मैंने जो कुछ भी पढ़ा है, और व्यक्तिगत अनुभव से, आपका सबसे अच्छा विकल्प डेटा के छोटे बिट्स के साथ काम करना है और जितनी जल्दी हो सके उन्हें भेजना है। आप रिसीवर के पक्ष में कोई जिटर बफरिंग करना चाहते हैं।

यह एक वीओआईपी आवेदन के लिए प्रति सेकंड 50-100 पैकेट भेजने के लिए विशिष्ट है। 8000 हर्ट्ज पर यूला एन्कोडिंग के लिए, इसका परिणाम 80-160 बाइट्स का पैकेट आकार होगा। इसके लिए तर्क यह है कि कुछ पैकेट अनिवार्य रूप से गिरा दिए जाएंगे, और आप रिसीवर को जितना संभव हो उतना छोटा होना चाहते हैं। तो प्रति पैक 10ms या 20ms ऑडियो डेटा के साथ, एक गिराए गए पैकेट के परिणामस्वरूप एक छोटा सा हिचकी हो सकती है, लेकिन लगभग 2k ऑडियो डेटा (~ 250ms) खोने के रूप में उतनी ही खराब नहीं होती है।

इसके अतिरिक्त, एक बड़े पैकेट आकार के साथ, आपको भेजने से पहले प्रेषक के सभी डेटा जमा करना होगा। तो 50 एमएमएस के एक सामान्य नेटवर्क विलंबता के साथ, 20 पैकेट प्रति ऑडियो डेटा के साथ, रिसीवर यह नहीं सुन रहा है कि प्रेषक कम से कम 70ms के लिए क्या कहता है। अब कल्पना करें कि क्या होता है जब 250 एमएमएस ऑडियो एक बार में भेजा जा रहा है। 270ms प्रेषक बोलने वाले और रिसीवर के बीच उस ऑडियो को चलाने के बीच समाप्त हो जाएगा।

उपयोगकर्ता यहां और वहां पैकेट हानि के अधिक क्षमा चाहते हैं, जिसके परिणामस्वरूप उप-पैरा ऑडियो गुणवत्ता होती है, क्योंकि अधिकांश टेलीफ़ोन की ऑडियो गुणवत्ता शुरू करने के लिए बहुत अच्छी नहीं है। हालांकि, उपयोगकर्ताओं को आधुनिक टेलीफोन सर्किट पर बहुत कम विलंबता के लिए भी उपयोग किया जाता है, इसलिए 250 एमएमएस की राउंड-ट्रिप देरी शुरू करना बेहद निराशाजनक हो सकता है।

अब, जहां तक ​​बफरिंग लागू करने के लिए, मुझे एक कतार का उपयोग करने के लिए एक अच्छी रणनीति मिली है (जो, यहां .NET का उपयोग कर :) :), और उसके बाद उस वर्ग में लपेटें जो वांछित न्यूनतम और अधिकतम संख्या में पैकेट ट्रैक करता है कतार में। कठोर लॉकिंग का उपयोग करें क्योंकि आप इसे कई धागे से एक्सेस कर सकते हैं। यदि कतार "बोटम आउट" है और इसमें शून्य पैकेट हैं (बफर अंडरन), एक ध्वज सेट करें और पैकेट गिनती तक वांछित न्यूनतम तक पहुंचने तक शून्य वापस लौटें। आपके उपभोक्ता को वापस लौटने के लिए जांच करनी होगी और आउटपुट बफर में कुछ भी कतार नहीं लेनी होगी। वैकल्पिक रूप से आपका उपभोक्ता अंतिम पैकेट का ट्रैक रख सकता है और इसे बार-बार दबा सकता है, जो लूपिंग ऑडियो का कारण बन सकता है, लेकिन कुछ मामलों में जो चुप्पी से बेहतर "ध्वनि" कर सकता है। आपको तब तक ऐसा करना होगा जब तक निर्माता कम से कम तक पहुंचने के लिए कतार में पर्याप्त पैकेट रखता है। इसके परिणामस्वरूप उपयोगकर्ता के लिए चुप्पी की लंबी अवधि होगी, लेकिन आमतौर पर शॉर्ट, लगातार अवधि की मौन (चापलूसी) से बेहतर स्वीकार्य होता है। यदि आपको पैकेट का फट जाता है और निर्माता कतार को भरता है (वांछित अधिकतम तक पहुंचता है), तो आप या तो नए पैकेट को अनदेखा करना शुरू कर सकते हैं, या न्यूनतम पर वापस जाने के लिए कतार के सामने पर्याप्त पैकेट छोड़ सकते हैं।

हालांकि उन न्यूनतम/अधिकतम मूल्यों को चुनना कठिन है।आप प्रेषक और रिसीवर के बीच न्यूनतम विलंबता के साथ चिकनी ऑडियो (कोई अंडरनन्स) को संतुलित करने की कोशिश कर रहे हैं। वीओआईपी मजेदार है लेकिन यह निश्चित रूप से निराशाजनक हो सकता है! सौभाग्य!

+0

आपके इनपुट के लिए धन्यवाद। मुझें यह पसंद है! – Xiphias3

संबंधित मुद्दे