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