webrtc 接收packt包后处理

9 篇文章 0 订阅
4 篇文章 0 订阅
逻辑上讲,webrtc收到rtp包以后,是组帧操作。也就是packet到frame。
注意rtp包的封包形式,stapA FU-A,单一单元组合包。可以参考 http://blog.csdn.net/jwybobo2007/article/details/7054140
int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
                uint8_t* frame_buffer,
                VCMDecodeErrorMode decode_error_mode,
                const FrameData& frame_data) {
    if (packet.frameType == kEmptyFrame) {
        // Update sequence number of an empty packet.
        // Only media packets are inserted into the packet list.    
        InformOfEmptyPacket(packet.seqNum);
        return 0;
    }

    if (packets_.size() == kMaxPacketsInSession) {
        LOG(LS_ERROR) << "Max number of packets per frame has been reached.";
        return -1;
    }

    // Find the position of this packet in the packet list in sequence number
    // order and insert it. Loop over the list in reverse order.
   // 1. handle duplicate
   // 2. handle newer
   // 3. handle last packet
   // 4. handle late packet (乱序)
    ReversePacketIterator rit = packets_.rbegin();
    for (; rit != packets_.rend(); ++rit)
        if (LatestSequenceNumber(packet.seqNum, (*rit).seqNum) == packet.seqNum)
        break;

        // Check for duplicate packets.
        if (rit != packets_.rend() && (*rit).seqNum == packet.seqNum &&
                (*rit).sizeBytes > 0)
            return -2;

        if (packet.codec == kVideoCodecH264) {
            frame_type_ = packet.frameType;
            if (packet.is_first_packet_in_frame &&
                (first_packet_seq_num_ == -1 ||
                    IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum))) {
                first_packet_seq_num_ = packet.seqNum;
            }
        //the last packet
        if (packet.markerBit &&
            (last_packet_seq_num_ == -1 ||
                IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_))) {
                last_packet_seq_num_ = packet.seqNum;
        }
    } else {
        // Only insert media packets between first and last packets (when
        // available).
        // Placing check here, as to properly account for duplicate packets.
        // Check if this is first packet (only valid for some codecs)
        // Should only be set for one packet per session.
        if (packet.is_first_packet_in_frame && first_packet_seq_num_ == -1) {
            // The first packet in a frame signals the frame type.
            frame_type_ = packet.frameType;
            // Store the sequence number for the first packet.
            first_packet_seq_num_ = static_cast<int>(packet.seqNum);
        } else if (first_packet_seq_num_ != -1 &&
            IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum)) {
            LOG(LS_WARNING) << "Received packet with a sequence number which is out "
            "of frame boundaries";
            return -3;
        } else if (frame_type_ == kEmptyFrame && packet.frameType != kEmptyFrame) {
            // Update the frame type with the type of the first media packet.
            // TODO(mikhal): Can this trigger?
            frame_type_ = packet.frameType;
        }

        // Track the marker bit, should only be set for one packet per session.
        if (packet.markerBit && last_packet_seq_num_ == -1) {
            last_packet_seq_num_ = static_cast<int>(packet.seqNum);
        } else if (last_packet_seq_num_ != -1 &&
            IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
            LOG(LS_WARNING) << "Received packet with a sequence number which is out "
            "of frame boundaries";
            return -3;
        }
    }

    // The insert operation invalidates the iterator |rit|.
   //the position for insert
    PacketIterator packet_list_it = packets_.insert(rit.base(), packet);
    //insert the data,
    size_t returnLength = InsertBuffer(frame_buffer, packet_list_it);
    UpdateCompleteSession();
    if (decode_error_mode == kWithErrors)
        decodable_ = true;
    else if (decode_error_mode == kSelectiveErrors)
        UpdateDecodableSession(frame_data);
    return static_cast<int>(returnLength);
}
后面就是如何插入这个包到frame了,哈哈
size_t VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer,
        PacketIterator packet_it) {
      VCMPacket& packet = *packet_it;
    PacketIterator it;

    // Calculate the offset into the frame buffer for this packet.
    size_t offset = 0;
    for (it = packets_.begin(); it != packet_it; ++it)
        offset += (*it).sizeBytes;

    // Set the data pointer to pointing to the start of this packet in the
    // frame buffer.
    const uint8_t* packet_buffer = packet.dataPtr;
    packet.dataPtr = frame_buffer + offset;

    // We handle H.264 STAP-A packets in a special way as we need to remove the
    // two length bytes between each NAL unit, and potentially add start codes.
    // TODO(pbos): Remove H264 parsing from this step and use a fragmentation
    // header supplied by the H264 depacketizer.
    const size_t kH264NALHeaderLengthInBytes = 1;
    const size_t kLengthFieldLength = 2;
    if (packet.video_header.codec == kRtpVideoH264 &&
            packet.video_header.codecHeader.H264.packetization_type == kH264StapA) {
        size_t required_length = 0;
        const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
        while (nalu_ptr < packet_buffer + packet.sizeBytes) {
            size_t length = BufferToUWord16(nalu_ptr);
            required_length +=
            length + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
            nalu_ptr += kLengthFieldLength + length;
        }
        ShiftSubsequentPackets(packet_it, required_length);
        nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
        uint8_t* frame_buffer_ptr = frame_buffer + offset;
        while (nalu_ptr < packet_buffer + packet.sizeBytes) {
            size_t length = BufferToUWord16(nalu_ptr);
            nalu_ptr += kLengthFieldLength;
            frame_buffer_ptr += Insert(nalu_ptr, length, packet.insertStartCode,
            const_cast<uint8_t*>(frame_buffer_ptr));
            nalu_ptr += length;
        }
        packet.sizeBytes = required_length;
        return packet.sizeBytes;
    }
    ShiftSubsequentPackets(
        packet_it, packet.sizeBytes +
        (packet.insertStartCode ? kH264StartCodeLengthBytes : 0));

    packet.sizeBytes =
        Insert(packet_buffer, packet.sizeBytes, packet.insertStartCode,
                const_cast<uint8_t*>(packet.dataPtr));
    return packet.sizeBytes;
}

怎样才能确认一个完整包的结束
1.有第一包和最后一包
2.中间seq连续
void VCMSessionInfo::UpdateCompleteSession() {
  if (HaveFirstPacket() && HaveLastPacket()) {
    // Do we have all the packets in this session?
    bool complete_session = true;
    PacketIterator it = packets_.begin();
    PacketIterator prev_it = it;
    ++it;
    for (; it != packets_.end(); ++it) {
      if (!InSequence(it, prev_it)) {
        complete_session = false;
        break;
      }
      prev_it = it;
    }
    complete_ = complete_session;
  }
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前进的蜗牛啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值