blob: 03c156928d80b56ac54f893f060d6baf7284752f [file] [log] [blame]
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* Split an RTP payload (if possible and suitable) and insert into packet buffer.
*/
#include "mcu.h"
#include <string.h>
#include "signal_processing_library.h"
#include "neteq_error_codes.h"
int WebRtcNetEQ_SplitAndInsertPayload(RTPPacket_t *packet, PacketBuf_t *Buffer_inst,
SplitInfo_t *split_inst, WebRtc_Word16 *flushed)
{
int i_ok;
int len;
int i;
RTPPacket_t temp_packet;
WebRtc_Word16 localFlushed = 0;
const WebRtc_Word16 *pw16_startPayload;
*flushed = 0;
len = packet->payloadLen;
/* Copy to temp packet that can be modified. */
WEBRTC_SPL_MEMCPY_W8(&temp_packet,packet,sizeof(RTPPacket_t));
if (split_inst->deltaBytes == NO_SPLIT)
{
/* Not splittable codec */
i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, packet, &localFlushed);
*flushed |= localFlushed;
if (i_ok < 0)
{
return PBUFFER_INSERT_ERROR5;
}
}
else if (split_inst->deltaBytes < -10)
{
/* G711, PCM16B or G722, use "soft splitting" */
int split_size = packet->payloadLen;
int mult = WEBRTC_SPL_ABS_W32(split_inst->deltaBytes) - 10;
/* Find "chunk size" >= 20 ms and < 40 ms
* split_inst->deltaTime in this case contains the number of bytes per
* timestamp unit times 2
*/
while (split_size >= ((80 << split_inst->deltaTime) * mult))
{
split_size >>= 1;
}
/* Make the size an even value. */
if (split_size > 1)
{
split_size >>= 1;
split_size *= 2;
}
temp_packet.payloadLen = split_size;
pw16_startPayload = temp_packet.payload;
i = 0;
while (len >= (2 * split_size))
{
/* insert every chunk */
i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, &temp_packet, &localFlushed);
*flushed |= localFlushed;
temp_packet.timeStamp += ((2 * split_size) >> split_inst->deltaTime);
i++;
temp_packet.payload = &(pw16_startPayload[(i * split_size) >> 1]);
temp_packet.starts_byte1 = temp_packet.starts_byte1 ^ (split_size & 0x1);
len -= split_size;
if (i_ok < 0)
{
return PBUFFER_INSERT_ERROR1;
}
}
/* Insert the rest */
temp_packet.payloadLen = len;
i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, &temp_packet, &localFlushed);
*flushed |= localFlushed;
if (i_ok < 0)
{
return PBUFFER_INSERT_ERROR2;
}
}
else
{
/* Frame based codec, use hard splitting. */
i = 0;
pw16_startPayload = temp_packet.payload;
while (len >= split_inst->deltaBytes)
{
temp_packet.payloadLen = split_inst->deltaBytes;
i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, &temp_packet, &localFlushed);
*flushed |= localFlushed;
i++;
temp_packet.payload = &(pw16_startPayload[(i * split_inst->deltaBytes) >> 1]);
temp_packet.timeStamp += split_inst->deltaTime;
temp_packet.starts_byte1 = temp_packet.starts_byte1 ^ (split_inst->deltaBytes
& 0x1);
if (i_ok < 0)
{
return PBUFFER_INSERT_ERROR3;
}
len -= split_inst->deltaBytes;
}
if (len > 0)
{
/* Must be a either an error or a SID frame at the end of the packet. */
temp_packet.payloadLen = len;
i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, &temp_packet, &localFlushed);
*flushed |= localFlushed;
if (i_ok < 0)
{
return PBUFFER_INSERT_ERROR4;
}
}
}
return 0;
}