Beispiel #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;
   }
}
Beispiel #2
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;
}
Beispiel #3
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;
}