예제 #1
0
UtlBoolean MpDecodeBuffer::needsResampling(const MpDecoderBase& rDecoder) const
{
   if (rDecoder.getInfo()->getCodecType() != SdpCodec::SDP_CODEC_TONES &&
      rDecoder.getInfo()->getSamplingRate() != m_samplesPerSec)
   {
      return TRUE;
   }
   else
   {
      return FALSE;
   }
}
예제 #2
0
UtlBoolean MprDecode::handleSelectCodecs(SdpCodec* pCodecs[], int numCodecs)
{
   int i;
   SdpCodec* pCodec;
   int payload;
   SdpCodec::SdpCodecTypes ourCodec;
   SdpCodec::SdpCodecTypes oldSdpType = SdpCodec::SDP_CODEC_UNKNOWN;
   OsStatus ret;
   MpDecoderBase* pNewDecoder;
   MpDecoderBase* pOldDecoder;
   MpCodecFactory* pFactory = MpCodecFactory::getMpCodecFactory();
   int allReusable = 1;
   int canReuse;
#if 0
   osPrintf("MprDecode::handleSelectCodecs(%d codec%s):\n",
      numCodecs, ((1 == numCodecs) ? "" : "s"));
#endif
   if (OsSysLog::willLog(FAC_MP, PRI_DEBUG))
   {
      for (i=0; i<numCodecs; i++) {
         pCodec = pCodecs[i];
         OsSysLog::add(FAC_MP, PRI_DEBUG,
                       "MprDecode::handleSelectCodecs "
                       "pCodecs[%d]->getCodecType() = %d, "
                       "pCodecs[%d]->getCodecPayloadFormat() = %d",
                       i, pCodec->getCodecType(),
                       i, pCodec->getCodecPayloadFormat());
            }
   }

   // Check to see if all codecs in pCodecs can be handled by codecs
   // in mpCurrentCodecs.
   for (i=0; i<numCodecs; i++) {
      pCodec = pCodecs[i];
      ourCodec = pCodec->getCodecType();
      payload = pCodec->getCodecPayloadFormat();
#if 0
      osPrintf("  #%d: New=0x%p/i:%d/x:%d, ",
         i, ourCodec, payload);
#endif
      pOldDecoder = mpConnection->mapPayloadType(payload);
      if (NULL != pOldDecoder) {
         oldSdpType = pOldDecoder->getInfo()->getCodecType();
#if 0
         osPrintf("  Old=0x%p/i:%d", oldSdpType);
#endif
         canReuse = (ourCodec == oldSdpType)
            || ((SdpCodec::SDP_CODEC_G729AB == ourCodec)
                            && (SdpCodec::SDP_CODEC_G729A == oldSdpType))
            || ((SdpCodec::SDP_CODEC_G729A == ourCodec)
                            && (SdpCodec::SDP_CODEC_G729AB == oldSdpType));
      } else {
         // osPrintf("  no Old");
         canReuse = 0;
      }
      allReusable &= canReuse;
#if 0
      osPrintf(" i:%d/x:%d (%sreusable%s)\n", ourCodec, payload,
         (canReuse ? "" : "not "),
         (canReuse && (ourCodec != oldSdpType) ? "[*]" : ""));
#endif
   }

   // If the new list is not a subset of the old list, we have to copy
   // pCodecs into mpCurrentCodecs.
   if (!allReusable) {
      // Lock the m*Codecs members.
      OsLock lock(mLock);

      // Delete the current codecs.
      handleDeselectCodecs();

      mNumCurrentCodecs = numCodecs;
      mpCurrentCodecs = new MpDecoderBase*[numCodecs];

      for (i=0; i<numCodecs; i++) {
         pCodec = pCodecs[i];
         ourCodec = pCodec->getCodecType();
         payload = pCodec->getCodecPayloadFormat();
         ret = pFactory->createDecoder(ourCodec, payload, pNewDecoder);
         assert(OS_SUCCESS == ret);
         assert(NULL != pNewDecoder);
         pNewDecoder->initDecode(mpConnection);
         // Set up the DTMF notifier and media recorder, if any.
         if (pNewDecoder->getInfo()->isSignalingCodec())
         {
            pNewDecoder->handleSetDtmfNotify(mpNotify);
            pNewDecoder->setDtmfTerm(mpRecorder);
         }
         // Add this codec to mpConnection's payload type decoding table.
         mpConnection->addPayloadType(payload, pNewDecoder);
         mpCurrentCodecs[i] = pNewDecoder;
      }

      // Go back and add any signaling codecs to Jitter Buffer.
      for (i=0; i<numCodecs; i++) {
         if (mpCurrentCodecs[i]->getInfo()->isSignalingCodec()) {
            mpCurrentCodecs[i]->initDecode(mpConnection);
         }
      }
   }

   // Delete the list pCodecs.
   for (i=0; i<numCodecs; i++) {
      delete pCodecs[i];
   }
   delete[] pCodecs;
   return TRUE;
}
예제 #3
0
int MpDecodeBuffer::pushPacket(MpRtpBufPtr &rtpPacket, JitterBufferResult jbResult)
{
   unsigned int availableBufferSize =0;          // number of samples could be written to decoded buffer
   unsigned producedSamples = 0; // number of samples, returned from decoder
   uint8_t payloadType = 0;     // RTP packet payload type
   MpDecoderBase* decoder = NULL;  // decoder for the packet

   payloadType = rtpPacket->getRtpPayloadType();

   // Ignore illegal payload types
   if (payloadType >= JbPayloadMapSize)
      return 0;

   // Get decoder
   decoder = m_pDecoderMap[payloadType];
   if (decoder == NULL)
      return 0; // If we can't decode it, we must ignore it?

   // Calculate space available for decoded samples
   if (m_decodeBufferIn > m_decodeBufferOut || m_decodeBufferCount == 0)
   {
      availableBufferSize = g_decodeBufferSize-m_decodeBufferIn;
   }
   else
   {
      availableBufferSize = m_decodeBufferOut-m_decodeBufferIn;
   }

   MpAudioSample* pTmpDstBuffer = NULL;
   if (needsResampling(*decoder)) // for 8Khz flowgraph we will never resample
   {
      pTmpDstBuffer = m_resampleSrcBuffer;
   }
   else
   {
      pTmpDstBuffer = m_decodeHelperBuffer;
   }

   // decode samples from decoder, and copy them into decode buffer
   producedSamples = decoder->decode(rtpPacket, g_decodeHelperBufferSize, pTmpDstBuffer,
      jbResult == MP_JITTER_BUFFER_PLC);

   if (needsResampling(*decoder) && producedSamples > 0)
   {
      // need to resample
      MpResamplerBase* pResampler = m_pResamplerMap[payloadType];
      if (pResampler)
      {
         uint32_t inSampleCount = producedSamples;
         uint32_t inSampleProcessed = 0;
         OsStatus res = pResampler->resample(pTmpDstBuffer, inSampleCount, inSampleProcessed,
            m_decodeHelperBuffer, g_decodeHelperBufferSize, producedSamples);
         assert(res == OS_SUCCESS);
         if (res != OS_SUCCESS)
         {
            OsSysLog::add(FAC_AUDIO, PRI_ERR, "Resampling failure for payload format %d. Status %d.",
               payloadType, (int)res);
            return 0;
         }
      }
      else
      {
         // we can't resample, and can't decode
         OsSysLog::add(FAC_AUDIO, PRI_ERR, "Resampling is needed for payload format %d, but no such resampler is available.",
            payloadType);
         return 0;
      }
   }

   // don't even think about resampling noise, it still sounds noisy!
   if (producedSamples == 0 &&
      decoder->getInfo()->getCodecType() != SdpCodec::SDP_CODEC_TONES)
   {
      // if decoder didn't produce samples from RTP packet, generate noise according to decoder frame size
      int decoderSamplesPerFrame = decoder->getInfo()->getNumSamplesPerFrame();
      m_pNoiseGenerator->generateComfortNoise(m_decodeHelperBuffer, decoderSamplesPerFrame);
      producedSamples = decoderSamplesPerFrame;
   }

   int addedSamples = 0;
   // now we have decoded & resampled samples in m_decodeHelperBuffer, with decodedSamples count
   // copy them into main buffer
   if (producedSamples > 0)
   {
      // count1 is number of samples to copy before wrapping occurs
      int count1 = min(producedSamples, availableBufferSize);
      // count 2 is number of samples to copy after wrapping
      int count2 = producedSamples - count1;
      memcpy(m_decodeBuffer + m_decodeBufferIn, m_decodeHelperBuffer, count1 * sizeof(MpAudioSample));
      addedSamples += count1;
      if (count2 > 0)
      {
         count2 = min(count2, m_decodeBufferOut); // reduce count2 by available space since start of array
         memcpy(m_decodeBuffer, m_decodeHelperBuffer + count1, count2 * sizeof(MpAudioSample)); // copy to beginning of buffer
         addedSamples += count2;
      }
   }

   // Update buffer state
   m_decodeBufferCount += addedSamples;
   m_decodeBufferIn += addedSamples;
   // Reset write pointer if we reach end of buffer
   if (m_decodeBufferIn >= g_decodeBufferSize)
      m_decodeBufferIn -= g_decodeBufferSize;

   return 0;
}
예제 #4
0
UtlBoolean MprDecode::doProcessFrame(MpBufPtr inBufs[],
                                    MpBufPtr outBufs[],
                                    int inBufsSize,
                                    int outBufsSize,
                                    UtlBoolean isEnabled,
                                    int samplesPerFrame,
                                    int samplesPerSecond)
{
#ifdef DEBUG_DECODING /* [ */
static int numFramesForWarnings = 0;
static int numWarnings = 0;
#endif /* DEBUG_DECODING ] */

   MpBufPtr rtp;
   MpBufPtr out;

#ifdef DEBUG_DECODING /* [ */
   numFramesForWarnings++;
#endif /* DEBUG_DECODING ] */

   MpDecoderBase* pCurDec;
   Sample* pSamples = NULL;

   mFrameCounter++;

   if (0 == outBufsSize) return FALSE;

   if (!isEnabled) {
      mPreloading = 1;
      *outBufs = MpBuf_getFgSilence();
      return TRUE;
   }

   {
      MprDejitter* pDej = getMyDejitter();
      int packetLen;
      int pt;

      while (NULL != (rtp = pDej->pullPacket())) {
         pt = MprDejitter::getPayloadType(rtp);
         pCurDec = mpConnection->mapPayloadType(pt);
         if (NULL != pCurDec) {
            unsigned char* pRtpH;
            pRtpH = ((unsigned char*) MpBuf_getStorage(rtp)) + 1;
            if (0x80 == (0x80 & *pRtpH)) {
               if ((mFrameLastMarkerNotice + MARKER_WAIT_FRAMES) <
                         mFrameCounter) {
                  mNumMarkerNotices = 0;
               }
               if (mNumMarkerNotices++ < MAX_MARKER_NOTICES)
               {
                  // osPrintf("MprDecode: RTP marker bit ON\n");
                  mFrameLastMarkerNotice = mFrameCounter;
               }
            }
            packetLen = pCurDec->decodeIn(rtp);
            if (packetLen > 0) {
               pushIntoJitterBuffer(rtp, packetLen);
            }
         }
         MpBuf_delRef(rtp);
      }
   }

   out = MpBuf_getBuf(MpMisc.UcbPool, samplesPerFrame, 0, MP_FMT_T12);
   if (out)
   {
      pSamples = MpBuf_getSamples(out);
      memset(pSamples, 0, samplesPerFrame * sizeof(Sample));
      MpBuf_setSpeech(out, MP_SPEECH_SILENT);
   }
   JB_inst* pJBState = mpConnection->getJBinst();
   if (pJBState) {
      // This should be a JB_something or other.  However the only
      // current choices is a short or long equivalant and this needs
      // to be a plain old int:
      int outLen;
      int res;
      res = JB_RecOut(pJBState, pSamples, &outLen);
      MpBuf_setSpeech(out, MP_SPEECH_UNKNOWN);
   }

   *outBufs = out;
   Nprintf("Decode_doPF: returning 0x%p\n", out, 0,0,0,0,0);
   return TRUE;
}