/*
* Copyright (C) 2013 - 2017 Sony Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ldacBT_internal.h"
/* Get LDAC library version */
#define LDACBT_LIB_VER_MAJOR 2
#define LDACBT_LIB_VER_MINOR 0
#define LDACBT_LIB_VER_BRANCH 2
LDACBT_API int ldacBT_get_version( void )
{
return ((LDACBT_LIB_VER_MAJOR)<<16)|((LDACBT_LIB_VER_MINOR)<<8)|(LDACBT_LIB_VER_BRANCH);
}
/* Get LDAC handle */
LDACBT_API HANDLE_LDAC_BT ldacBT_get_handle( void )
{
HANDLE_LDAC_BT hLdacBT;
hLdacBT = (HANDLE_LDAC_BT)malloc( sizeof(STRUCT_LDACBT_HANDLE) );
if( hLdacBT == NULL ){ return NULL; }
/* Get ldaclib Handler */
if( (hLdacBT->hLDAC = ldaclib_get_handle()) == NULL ){
ldacBT_free_handle( hLdacBT );
return NULL;
}
ldacBT_param_clear( hLdacBT );
return hLdacBT;
}
/* Free LDAC handle */
LDACBT_API void ldacBT_free_handle( HANDLE_LDAC_BT hLdacBT )
{
if( hLdacBT == NULL ){ return; }
if( hLdacBT->hLDAC != NULL ){
/* close ldaclib handle */
if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){
ldaclib_free_encode( hLdacBT->hLDAC );
}
/* free ldaclib handle */
ldaclib_free_handle( hLdacBT->hLDAC );
hLdacBT->hLDAC = NULL;
}
/* free ldacbt handle */
free( hLdacBT );
}
/* Close LDAC handle */
LDACBT_API void ldacBT_close_handle( HANDLE_LDAC_BT hLdacBT )
{
if( hLdacBT == NULL ){ return; }
if( hLdacBT->hLDAC != NULL ){
/* close ldaclib handle */
if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){
ldaclib_free_encode( hLdacBT->hLDAC );
}
/* clear error code */
ldaclib_clear_error_code(hLdacBT->hLDAC);
ldaclib_clear_internal_error_code(hLdacBT->hLDAC);
}
/* clear ldacbt handle */
ldacBT_param_clear( hLdacBT );
}
/* Get ERROR CODE */
LDACBT_API int ldacBT_get_error_code( HANDLE_LDAC_BT hLdacBT )
{
int error_code;
if( hLdacBT == NULL ){return LDACBT_ERR_FATAL_HANDLE<<10;}
ldacBT_check_ldaclib_error_code( hLdacBT );
if( hLdacBT->error_code_api == LDACBT_GET_LDACLIB_ERROR_CODE ){
error_code = LDACBT_ERR_FATAL << 20 | hLdacBT->error_code;
}else if( hLdacBT->error_code_api != LDACBT_ERR_NONE ){
error_code = hLdacBT->error_code_api << 20 | hLdacBT->error_code;
}else{
error_code = hLdacBT->error_code_api << 20;
}
return error_code;
}
/* Get Configured Sampling frequency */
LDACBT_API int ldacBT_get_sampling_freq( HANDLE_LDAC_BT hLdacBT )
{
if( hLdacBT == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE )
{
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
return hLdacBT->pcm.sf;
}
/* Get bitrate */
LDACBT_API int ldacBT_get_bitrate( HANDLE_LDAC_BT hLdacBT )
{
if( hLdacBT == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE )
{
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
return hLdacBT->bitrate;
}
/* Init LDAC handle for ENCODE */
LDACBT_API int ldacBT_init_handle_encode( HANDLE_LDAC_BT hLdacBT, int mtu, int eqmid,
int cm, LDACBT_SMPL_FMT_T fmt, int sf )
{
LDAC_RESULT result;
int sfid, frame_samples, cci;
int nbasebands, grad_mode, grad_qu_l, grad_qu_h, grad_ofst_l, grad_ofst_h, abc_flag;
P_LDACBT_CONFIG pCfg;
const int a_cci_nch[] = { 1, 2, 2 };
/* check arguments */
if( hLdacBT == NULL ){ return LDACBT_E_FAIL; }
if( (hLdacBT->error_code_api = ldacBT_assert_mtu( mtu )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL;
}
if( (hLdacBT->error_code_api = ldacBT_assert_eqmid( eqmid )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL;
}
if( (hLdacBT->error_code_api = ldacBT_assert_cm( cm )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL;
}
if( (hLdacBT->error_code_api = ldacBT_assert_sample_format( fmt )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL;
}
if( (hLdacBT->error_code_api = ldacBT_assert_pcm_sampling_freq( sf )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL;
}
ldacBT_close_handle( hLdacBT );
/* initialize handle for encode processing */
hLdacBT->proc_mode = LDACBT_PROCMODE_ENCODE;
hLdacBT->flg_encode_flushed = FALSE;
/* transport setting */
/* The ldac frame header is REQUIRED for A2DP streaming. */
hLdacBT->transport = TRUE;
hLdacBT->tx.mtu = mtu;
hLdacBT->tx.pkt_hdr_sz = LDACBT_TX_HEADER_SIZE;
hLdacBT->tx.tx_size = LDACBT_MTU_REQUIRED;
hLdacBT->tx.pkt_type = _2_DH5;
/* - BT TRANS HEADER etc */
hLdacBT->tx.tx_size -= hLdacBT->tx.pkt_hdr_sz;
if( hLdacBT->tx.tx_size > (hLdacBT->tx.mtu - hLdacBT->tx.pkt_hdr_sz) ){
/* never happen, mtu must be larger than LDACBT_MTU_REQUIRED(2DH5) */
hLdacBT->tx.tx_size = (hLdacBT->tx.mtu - hLdacBT->tx.pkt_hdr_sz);
}
/* channel configration */
cci = ldacBT_cm_to_cci(cm);
hLdacBT->cm = cm;
hLdacBT->cci = cci;
/* input pcm configuration */
hLdacBT->pcm.ch = a_cci_nch[cci];
hLdacBT->pcm.sf = sf;
hLdacBT->pcm.fmt = fmt;
switch(hLdacBT->pcm.fmt){
case LDACBT_SMPL_FMT_S16:
hLdacBT->pcm.wl = 2;
break;
case LDACBT_SMPL_FMT_S24:
hLdacBT->pcm.wl = 3;
break;
case LDACBT_SMPL_FMT_S32:
case LDACBT_SMPL_FMT_F32:
hLdacBT->pcm.wl = 4;
break;
default:
// must be rejected by ldacBT_assert_sample_format()
hLdacBT->pcm.wl = 4;
break;
}
/* initilize ldac encode */
/* Get sampling frequency index */
result = ldaclib_get_sampling_rate_index( hLdacBT->pcm.sf, &sfid );
if( LDAC_FAILED ( result ) ){
hLdacBT->error_code_api = LDACBT_ERR_ILL_SAMPLING_FREQ;
return LDACBT_E_FAIL;
}
hLdacBT->sfid = sfid;
/* Get number of frame samples */
result = ldaclib_get_frame_samples(sfid, &frame_samples);
if (LDAC_FAILED(result)) {
hLdacBT->error_code_api = LDACBT_ERR_ILL_SAMPLING_FREQ;
return LDACBT_E_FAIL;
}
hLdacBT->frm_samples = frame_samples;
/* Set Parameters by Encode Quality Mode Index */
hLdacBT->eqmid = eqmid;
/* get frame_length of EQMID */
pCfg = ldacBT_get_config( hLdacBT->eqmid, hLdacBT->tx.pkt_type );
/* set frame_length */
hLdacBT->frmlen_tx = hLdacBT->pcm.ch * pCfg->frmlen_1ch;
hLdacBT->frmlen = hLdacBT->frmlen_tx;
if (hLdacBT->transport) {
/* Adjust frame_length for Transport Header Data */
hLdacBT->frmlen -= LDACBT_FRMHDRBYTES;
}
/* Calculate how many LDAC frames fit into payload packet */
hLdacBT->tx.nfrm_in_pkt = hLdacBT->tx.tx_size / hLdacBT->frmlen_tx;
/* Get ldac encode setting */
result = ldaclib_get_encode_setting( pCfg->frmlen_1ch, sfid, &nbasebands, &grad_mode,
&grad_qu_l, &grad_qu_h, &grad_ofst_l, &grad_ofst_h, &abc_flag);
if (LDAC_FAILED(result)) {
hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
return LDACBT_E_FAIL;
}
/* Set Configuration Information */
result = ldaclib_set_config_info( hLdacBT->hLDAC, hLdacBT->sfid, hLdacBT->cci,
hLdacBT->frmlen, hLdacBT->frm_status);
if (LDAC_FAILED(result)) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if (result != LDAC_S_OK) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
/* Set Encoding Information */
result = ldaclib_set_encode_info(hLdacBT->hLDAC, nbasebands, grad_mode,
grad_qu_l, grad_qu_h, grad_ofst_l, grad_ofst_h, abc_flag);
if (LDAC_FAILED(result)) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if (result != LDAC_S_OK) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
/* Initialize ldaclib for Encoding */
result = ldaclib_init_encode(hLdacBT->hLDAC);
if (LDAC_FAILED(result)) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if (result != LDAC_S_OK) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
/* reset target eqmid as current setting */
hLdacBT->tgt_eqmid = hLdacBT->eqmid;
hLdacBT->tgt_nfrm_in_pkt = hLdacBT->tx.nfrm_in_pkt;
hLdacBT->tgt_frmlen = hLdacBT->frmlen;
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
/* get bitrate */
hLdacBT->bitrate = ldacBT_frmlen_to_bitrate( hLdacBT->frmlen, hLdacBT->transport,
hLdacBT->pcm.sf, hLdacBT->frm_samples );
return (hLdacBT->error_code_api==LDACBT_ERR_NONE?LDACBT_S_OK:LDACBT_E_FAIL);
}
/* Set Encode Quality Mode index */
LDACBT_API int ldacBT_set_eqmid( HANDLE_LDAC_BT hLdacBT, int eqmid )
{
if( hLdacBT == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
if( (hLdacBT->error_code_api = ldacBT_assert_eqmid( eqmid )) != LDACBT_ERR_NONE ){
return LDACBT_E_FAIL; /* fatal */
}
ldacBT_set_eqmid_core( hLdacBT, eqmid );
return LDACBT_S_OK;
}
/* Get Encode Quality Mode index */
LDACBT_API int ldacBT_get_eqmid( HANDLE_LDAC_BT hLdacBT )
{
if( hLdacBT == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
return hLdacBT->tgt_eqmid;
}
/* Alter encode quality mode index */
LDACBT_API int ldacBT_alter_eqmid_priority( HANDLE_LDAC_BT hLdacBT, int priority )
{
int target_eqmid;
if( hLdacBT == NULL ){ return LDACBT_E_FAIL; }
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
if( (priority != LDACBT_EQMID_INC_QUALITY) &&
(priority != LDACBT_EQMID_INC_CONNECTION )
){
hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
return LDACBT_E_FAIL;
}
target_eqmid = ldacBT_get_altered_eqmid( hLdacBT, priority);
if( target_eqmid < 0 ){
hLdacBT->error_code_api = LDACBT_ERR_ALTER_EQMID_LIMITED;
return LDACBT_E_FAIL;
}
ldacBT_set_eqmid_core( hLdacBT, target_eqmid );
return LDACBT_S_OK;
}
/* LDAC encode proccess */
LDACBT_API int ldacBT_encode( HANDLE_LDAC_BT hLdacBT, void *p_pcm, int *pcm_used,
unsigned char *p_stream, int *stream_sz, int *frame_num )
{
LDAC_RESULT result;
LDACBT_SMPL_FMT_T fmt;
LDACBT_TRANSPORT_FRM_BUF *ptfbuf;
LDACBT_PCM_RING_BUF *ppcmring;
P_LDACBT_CONFIG pCfg;
int frmlen, frmlen_wrote, frmlen_adj;
int frm_status, flg_Do_Encode;
int nFrmToPkt, ch, wl;
unsigned char *p_ldac_transport_frame;
unsigned char a_frm_header[LDACBT_FRMHDRBYTES + 2];
if( hLdacBT == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->hLDAC == NULL ){
return LDACBT_E_FAIL;
}
if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
return LDACBT_E_FAIL;
}
/* Clear Error Codes */
hLdacBT->error_code_api = LDACBT_ERR_NONE;
ldaclib_clear_error_code( hLdacBT->hLDAC );
ldaclib_clear_internal_error_code( hLdacBT->hLDAC );
if( ( pcm_used == NULL) ||
( p_stream == NULL ) ||
( stream_sz == NULL ) ||
( frame_num == NULL )
){
hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
return LDACBT_E_FAIL;
}
/* reset parameters */
*pcm_used = 0;
*stream_sz = 0;
*frame_num = 0;
flg_Do_Encode = 0;
fmt = hLdacBT->pcm.fmt;
ch = hLdacBT->pcm.ch;
wl = hLdacBT->pcm.wl;
ptfbuf = &hLdacBT->ldac_trns_frm_buf;
ppcmring = &hLdacBT->pcmring;
/* update input pcm data */
if( p_pcm != NULL ){
int nByteCpy, sz;
nByteCpy = LDACBT_ENC_LSU * wl * ch;
sz = ppcmring->nsmpl * wl * ch + nByteCpy;
if( sz < LDACBT_ENC_PCM_BUF_SZ ){
copy_data_ldac( p_pcm, ppcmring->buf + ppcmring->wp, nByteCpy );
ppcmring->wp += nByteCpy;
if( ppcmring->wp >= LDACBT_ENC_PCM_BUF_SZ ){
ppcmring->wp = 0;
}
ppcmring->nsmpl += LDACBT_ENC_LSU;
*pcm_used = nByteCpy;
}else{
/* Not enough space to copy.
* This will happen when the last encode process failed.
*/
*pcm_used = 0;
}
if( ppcmring->nsmpl >= hLdacBT->frm_samples )
{
flg_Do_Encode = 1;
}
}else{
if (hLdacBT->flg_encode_flushed != TRUE){
flg_Do_Encode = 1;
}
}
if( !flg_Do_Encode ){
/* nothing to do */
return LDACBT_S_OK;
}
/* update frame_length if needed */
if( (hLdacBT->tgt_eqmid != UNSET) && (hLdacBT->tgt_eqmid != hLdacBT->eqmid) ){
if( ptfbuf->nfrm_in == 0 ){
ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
}
else if( hLdacBT->tgt_nfrm_in_pkt > hLdacBT->tx.nfrm_in_pkt ){
/* for better connectivity, apply ASAP */
if( !hLdacBT->stat_alter_op ){
nFrmToPkt = hLdacBT->tgt_nfrm_in_pkt - ptfbuf->nfrm_in;
if( nFrmToPkt > 0 ){
pCfg = ldacBT_get_config(LDACBT_EQMID_END, hLdacBT->tx.pkt_type);
if( pCfg != NULL ){
do{
frmlen_adj = (hLdacBT->tx.tx_size - ptfbuf->used) / nFrmToPkt;
if( frmlen_adj > hLdacBT->tgt_frmlen ) {
frmlen_adj = hLdacBT->tgt_frmlen;
}
frmlen_adj -= LDACBT_FRMHDRBYTES;
if( frmlen_adj >= pCfg->frmlen ){
if( ldacBT_update_frmlen( hLdacBT, frmlen_adj ) == LDACBT_S_OK ){
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__ACTIVE;
break;
}
}
}while( --nFrmToPkt > 0 );
}
if( !hLdacBT->stat_alter_op ){
/* force to flash streams */
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__FLASH;
}
}
}
}
else{
/* wait the condition ptfbuf->nfrm_in == 0 for apply new frame_length */
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__STANDBY;
}
}
else if( hLdacBT->tgt_frmlen != hLdacBT->frmlen ){
if( ptfbuf->nfrm_in == 0 ){
ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
}else{
if( hLdacBT->tgt_nfrm_in_pkt == hLdacBT->tx.nfrm_in_pkt ){
ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
}else{
if( hLdacBT->tgt_nfrm_in_pkt > hLdacBT->tx.nfrm_in_pkt ){
/* for better connectivity, apply ASAP */
if( !hLdacBT->stat_alter_op ){
nFrmToPkt = hLdacBT->tgt_nfrm_in_pkt - ptfbuf->nfrm_in;
if( nFrmToPkt > 0 ){
frmlen_adj = (hLdacBT->tx.tx_size - ptfbuf->used) / nFrmToPkt;
if( frmlen_adj > hLdacBT->tgt_frmlen ) {
frmlen_adj = hLdacBT->tgt_frmlen;
}
if( ldacBT_update_frmlen( hLdacBT, frmlen_adj ) == LDACBT_S_OK ){
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__ACTIVE;
}
if( !hLdacBT->stat_alter_op ){
/* flash streams */
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__FLASH;
}
}
}
}else{
/* wait the condition ptfbuf->nfrm_in == 0 for apply new frame_length */
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__STANDBY;
}
}
}
}
/* check write space for encoded data */
ldaclib_get_encode_frame_length( hLdacBT->hLDAC, &frmlen );
if( (( ptfbuf->used + frmlen + LDACBT_FRMHDRBYTES) > hLdacBT->tx.tx_size) ||
(hLdacBT->stat_alter_op == LDACBT_ALTER_OP__FLASH) || /* need to flash streams? */
(( ptfbuf->used + frmlen + LDACBT_FRMHDRBYTES) >= LDACBT_ENC_STREAM_BUF_SZ )
)
{
copy_data_ldac( ptfbuf->buf, p_stream, ptfbuf->used );
*stream_sz = ptfbuf->used;
*frame_num = ptfbuf->nfrm_in;
clear_data_ldac( ptfbuf->buf, sizeof(char)*LDACBT_ENC_STREAM_BUF_SZ);
ptfbuf->used = 0;
ptfbuf->nfrm_in = 0;
if( hLdacBT->stat_alter_op != LDACBT_ALTER_OP__NON ){
/* update frame length */
ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
}
}
p_ldac_transport_frame = ptfbuf->buf + ptfbuf->used;
/* Encode Frame */
if( ppcmring->nsmpl > 0 ){
char *p_pcm_ring_r;
int nsmpl_to_clr;
nsmpl_to_clr = hLdacBT->frm_samples - ppcmring->nsmpl;
if( nsmpl_to_clr > 0 ){
int pos, nBytesToZero;
pos = ppcmring->rp + ppcmring->nsmpl * wl * ch;
nBytesToZero = nsmpl_to_clr * wl * ch;
while( nBytesToZero > 0 ){
int clearBytes;
clearBytes = nBytesToZero;
if ( pos + clearBytes >= LDACBT_ENC_PCM_BUF_SZ ){
clearBytes = (LDACBT_ENC_PCM_BUF_SZ - pos);
}
clear_data_ldac( ppcmring->buf + pos, clearBytes);
nBytesToZero -= clearBytes;
if( (pos += clearBytes) >= LDACBT_ENC_PCM_BUF_SZ ){
pos = 0;
}
}
}
p_pcm_ring_r = ppcmring->buf + ppcmring->rp;
ldacBT_prepare_pcm_encode( p_pcm_ring_r, hLdacBT->pp_pcm, hLdacBT->frm_samples, ch, fmt );
result = ldaclib_encode(hLdacBT->hLDAC, hLdacBT->pp_pcm, (LDAC_SMPL_FMT_T)fmt,
p_ldac_transport_frame+LDACBT_FRMHDRBYTES, &frmlen_wrote);
if( !LDAC_FAILED(result) ){
ppcmring->rp += hLdacBT->frm_samples * wl * ch;
ppcmring->nsmpl -= hLdacBT->frm_samples;
if( ppcmring->rp >= LDACBT_ENC_PCM_BUF_SZ ){ ppcmring->rp = 0; }
if( ppcmring->nsmpl < 0 ){ ppcmring->nsmpl = 0; }
}
}else{
result = ldaclib_flush_encode(hLdacBT->hLDAC, (LDAC_SMPL_FMT_T)fmt,
p_ldac_transport_frame+LDACBT_FRMHDRBYTES, &frmlen_wrote);
hLdacBT->flg_encode_flushed = TRUE;
}
if( LDAC_FAILED(result) ){
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if( result != LDAC_S_OK ){
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
if( frmlen_wrote > 0 ){
if( hLdacBT->transport == TRUE ){
/* Set Frame Header Data */
clear_data_ldac( a_frm_header, LDACBT_FRMHDRBYTES+2 );
/* Get Frame Header Information */
result = ldaclib_get_config_info(hLdacBT->hLDAC, &hLdacBT->sfid, &hLdacBT->cci,
&frmlen, &frm_status);
if( LDAC_FAILED(result) ){
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if (result != LDAC_S_OK) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
/* Set Frame Header */
result = ldaclib_set_frame_header(hLdacBT->hLDAC, a_frm_header, hLdacBT->sfid,
hLdacBT->cci, frmlen, frm_status);
if( LDAC_FAILED(result) ){
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
return LDACBT_E_FAIL;
}
else if (result != LDAC_S_OK) {
hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
}
copy_data_ldac( a_frm_header, p_ldac_transport_frame, LDACBT_FRMHDRBYTES );
frmlen_wrote += LDACBT_FRMHDRBYTES;
}
ptfbuf->used += frmlen_wrote;
ptfbuf->nfrm_in ++;
}
/* check for next frame buffer status */
if( *stream_sz == 0 ){
if( (( ptfbuf->used + frmlen_wrote) > hLdacBT->tx.tx_size) ||
( ptfbuf->nfrm_in >= LDACBT_NFRM_TX_MAX ) ||
(( ptfbuf->used + frmlen_wrote) >= LDACBT_ENC_STREAM_BUF_SZ ) ||
( p_pcm == NULL ) /* flush encode */
)
{
copy_data_ldac( ptfbuf->buf, p_stream, ptfbuf->used );
*stream_sz = ptfbuf->used;
*frame_num = ptfbuf->nfrm_in;
clear_data_ldac( ptfbuf->buf, sizeof(char)*LDACBT_ENC_STREAM_BUF_SZ);
ptfbuf->used = 0;
ptfbuf->nfrm_in = 0;
if( hLdacBT->stat_alter_op != LDACBT_ALTER_OP__NON ){
ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
}
}
}
return LDACBT_S_OK;
}