//-------------------------------------------------------------------------
    void RTPReceiverChannelAudio::onReceiverChannelAudioDeliverPackets()
    {
      RTPPacketQueue rtpPackets;
      RTCPPacketQueue rtcpPackets;
      UseChannelResourcePtr channelResource;
      {
        AutoRecursiveLock lock(*this);
        rtpPackets = mQueuedRTP;
        rtcpPackets = mQueuedRTCP;
        mQueuedRTP = RTPPacketQueue();
        mQueuedRTCP = RTCPPacketQueue();
        channelResource = mChannelResource;
      }

      if (!channelResource)
        return;

      while (rtpPackets.size() > 0) {
        auto packet = rtpPackets.front();
        channelResource->handlePacket(*packet);
        rtpPackets.pop();
      }

      while (rtcpPackets.size() > 0) {
        auto packet = rtcpPackets.front();
        channelResource->handlePacket(*packet);
        rtcpPackets.pop();
      }
    }
    //-------------------------------------------------------------------------
    bool RTPReceiverChannelAudio::handlePacket(RTPPacketPtr packet)
    {
      UseChannelResourcePtr channelResource;

      {
        AutoRecursiveLock lock(*this);
        if (isShuttingDown() || isShutdown())
          return false;
        channelResource = mChannelResource;
        bool shouldQueue = false;
        if (!channelResource)
          shouldQueue = true;
        if (mQueuedRTP.size() > 0)
          shouldQueue = true;
        if (shouldQueue) {
          mQueuedRTP.push(packet);
          if (1 == mQueuedRTP.size())
            IWakeDelegateProxy::create(mThisWeak.lock())->onWake();
          return true;
        }
      }

      if (!channelResource) return true;
      return channelResource->handlePacket(*packet);
    }
    //-------------------------------------------------------------------------
    bool RTPSenderChannelAudio::handlePacket(RTCPPacketPtr packet)
    {
      UseChannelResourcePtr channelResource;

      {
        AutoRecursiveLock lock(*this);
        channelResource = mChannelResource;
      }

      if (!channelResource) return false;
      return channelResource->handlePacket(*packet);
    }
    //-------------------------------------------------------------------------
    void RTPReceiverChannelAudio::onUpdate(ParametersPtr params)
    {
      ZS_LOG_TRACE(log("on update") + params->toDebug())

      UseChannelResourcePtr channelResource;
      {
        AutoRecursiveLock lock(*this);
        mParameters = make_shared<Parameters>(*params);
        channelResource = mChannelResource;
      }

      if (channelResource)
        channelResource->notifyUpdate(params);
    }
    //-------------------------------------------------------------------------
    void RTPReceiverChannelAudio::requestStats(PromiseWithStatsReportPtr promise, const StatsTypeSet &stats)
    {
      UseChannelResourcePtr channelResource;
      {
        AutoRecursiveLock lock(*this);
        channelResource = mChannelResource;
      }

      if (!channelResource) {
        promise->reject();
        return;
      }
      return channelResource->requestStats(promise, stats);
    }
    //-------------------------------------------------------------------------
    bool RTPReceiverChannelAudio::handlePacket(RTCPPacketPtr packet)
    {
      UseChannelResourcePtr channelResource;
      {
        AutoRecursiveLock lock(*this);
        if (mQueuedRTP.size() > 0) {
          mQueuedRTCP.push(packet);
          return true;
        }
        channelResource = mChannelResource;
      }

      if (!channelResource) return false;
      return channelResource->handlePacket(*packet);
    }