/*
|
* 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;
|
}
|