130 lines
3.9 KiB
C

/*
* Copyright (c) 2016, Athonet (www.athonet.com)
* Dragos Oancea <dragos.oancea@athonet.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __AMR_BE_H__
#include "bitshift.h"
#include "amr_be.h"
extern const int switch_amr_frame_sizes[];
/* Bandwidth Efficient AMR-NB */
/* https://tools.ietf.org/html/rfc4867#page-17 */
extern switch_bool_t switch_amr_pack_be(unsigned char *shift_buf, int n)
{
uint8_t save_toc, ft;
save_toc = shift_buf[1];
/* we must convert OA TOC -> BE TOC */
/* OA TOC
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|F| FT |Q|P1|P2|
+-+-+-+-+-+-+-+-+
F (1 bit): see definition in Section 4.3.2.
FT (4 bits, unsigned integer): see definition in Section 4.3.2.
Q (1 bit): see definition in Section 4.3.2.
P bits: padding bits, MUST be set to zero, and MUST be ignored on reception.
*/
/* BE TOC:
0 1 2 3 4 5
+-+-+-+-+-+-+
|F| FT |Q|
+-+-+-+-+-+-+
F = 0 , FT = XXXX , Q = 1
eg: Frame Types (FT): ftp://www.3gpp.org/tsg_sa/TSG_SA/TSGS_04/Docs/PDF/SP-99253.pdf - table 1a
*/
ft = save_toc >> 3 ; /* drop Q, P1, P2 */
ft &= ~(1 << 5); /* clear - will mark just 1 frame - bit F */
/* we only encode one frame, so bit 0 of TOC will be 0 */
shift_buf[0] |= (ft >> 1); /* first 3 bits of FT */
switch_amr_array_lshift(6, shift_buf+1, n);
/*make sure we clear the bit - it will be used as padding of the trailing byte */
shift_buf[1] |= 1 << 6; /* set bit Q instead of P1 */
if (( ft >> 0 ) & 1) {
/* set last bit of TOC instead of P2 */
shift_buf[1] |= 1 << 7;
} else {
/* reset last bit of TOC instead of P2 */
shift_buf[1] &= ~(1 << 7);
}
return SWITCH_TRUE;
}
extern switch_bool_t switch_amr_unpack_be(unsigned char *encoded_buf, uint8_t *tmp, int encoded_len)
{
int framesz, index;
uint8_t shift_tocs[2] = {0x00, 0x00};
uint8_t *shift_buf;
memcpy(shift_tocs, encoded_buf, 2);
/* shift for BE */
switch_amr_array_lshift(4, shift_tocs, 2);
shift_buf = encoded_buf + 1; /* skip CMR */
/* shift for BE */
switch_amr_array_lshift(2, shift_buf, encoded_len - 1);
/* get frame size */
index = ((shift_tocs[0] >> 3) & 0x0f);
if (index > 9 && index != 0xf) {
return SWITCH_FALSE;
}
framesz = switch_amr_frame_sizes[index];
tmp[0] = shift_tocs[0]; /* save TOC */
memcpy(&tmp[1], shift_buf, framesz);
return SWITCH_TRUE;
}
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/