1/*
2 * Copyright (C) 2013 - 2017 Sony Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ldacBT_internal.h"
18
19
20/* Get LDAC library version */
21#define LDACBT_LIB_VER_MAJOR   2
22#define LDACBT_LIB_VER_MINOR   0
23#define LDACBT_LIB_VER_BRANCH  2
24LDACBT_API int ldacBT_get_version( void )
25{
26    return ((LDACBT_LIB_VER_MAJOR)<<16)|((LDACBT_LIB_VER_MINOR)<<8)|(LDACBT_LIB_VER_BRANCH);
27}
28
29/* Get LDAC handle */
30LDACBT_API HANDLE_LDAC_BT ldacBT_get_handle( void )
31{
32    HANDLE_LDAC_BT hLdacBT;
33    hLdacBT = (HANDLE_LDAC_BT)malloc( sizeof(STRUCT_LDACBT_HANDLE) );
34    if( hLdacBT == NULL ){ return NULL; }
35
36    /* Get ldaclib Handler */
37    if( (hLdacBT->hLDAC = ldaclib_get_handle()) == NULL ){
38        ldacBT_free_handle( hLdacBT );
39        return NULL;
40    }
41
42    ldacBT_param_clear( hLdacBT );
43    return hLdacBT;
44}
45
46/* Free LDAC handle */
47LDACBT_API void ldacBT_free_handle( HANDLE_LDAC_BT hLdacBT )
48{
49    if( hLdacBT == NULL ){ return; }
50
51    if( hLdacBT->hLDAC != NULL ){
52        /* close ldaclib handle */
53        if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){
54            ldaclib_free_encode( hLdacBT->hLDAC );
55        }
56        /* free ldaclib handle */
57        ldaclib_free_handle( hLdacBT->hLDAC );
58        hLdacBT->hLDAC = NULL;
59    }
60    /* free ldacbt handle */
61    free( hLdacBT );
62}
63
64/* Close LDAC handle */
65LDACBT_API void ldacBT_close_handle( HANDLE_LDAC_BT hLdacBT )
66{
67    if( hLdacBT == NULL ){ return; }
68
69    if( hLdacBT->hLDAC != NULL ){
70        /* close ldaclib handle */
71        if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){
72            ldaclib_free_encode( hLdacBT->hLDAC );
73        }
74        /* clear error code */
75        ldaclib_clear_error_code(hLdacBT->hLDAC);
76        ldaclib_clear_internal_error_code(hLdacBT->hLDAC);
77    }
78    /* clear ldacbt handle */
79    ldacBT_param_clear( hLdacBT );
80}
81
82
83/* Get ERROR CODE */
84LDACBT_API int ldacBT_get_error_code( HANDLE_LDAC_BT hLdacBT )
85{
86    int error_code;
87    if( hLdacBT == NULL ){return LDACBT_ERR_FATAL_HANDLE<<10;}
88    ldacBT_check_ldaclib_error_code( hLdacBT );
89    if( hLdacBT->error_code_api == LDACBT_GET_LDACLIB_ERROR_CODE ){
90        error_code = LDACBT_ERR_FATAL << 20 | hLdacBT->error_code;
91    }else if( hLdacBT->error_code_api != LDACBT_ERR_NONE ){
92        error_code = hLdacBT->error_code_api << 20 | hLdacBT->error_code;
93    }else{
94        error_code = hLdacBT->error_code_api << 20;
95    }
96    return error_code;
97}
98
99
100/* Get Configured Sampling frequency */
101LDACBT_API int ldacBT_get_sampling_freq( HANDLE_LDAC_BT hLdacBT )
102{
103    if( hLdacBT == NULL ){
104        return LDACBT_E_FAIL;
105    }
106    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE )
107    {
108        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
109        return LDACBT_E_FAIL;
110    }
111    return hLdacBT->pcm.sf;
112}
113
114/* Get bitrate */
115LDACBT_API int  ldacBT_get_bitrate( HANDLE_LDAC_BT hLdacBT )
116{
117    if( hLdacBT == NULL ){
118        return LDACBT_E_FAIL;
119    }
120    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE )
121    {
122        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
123        return LDACBT_E_FAIL;
124    }
125    return hLdacBT->bitrate;
126}
127
128/* Init LDAC handle for ENCODE */
129LDACBT_API int ldacBT_init_handle_encode( HANDLE_LDAC_BT hLdacBT, int mtu, int eqmid,
130                                      int cm, LDACBT_SMPL_FMT_T fmt, int sf )
131{
132    LDAC_RESULT result;
133    int sfid, frame_samples, cci;
134    int nbasebands, grad_mode, grad_qu_l, grad_qu_h, grad_ofst_l, grad_ofst_h, abc_flag;
135    P_LDACBT_CONFIG pCfg;
136    const int a_cci_nch[] = { 1, 2, 2 };
137
138    /* check arguments */
139    if( hLdacBT == NULL ){ return LDACBT_E_FAIL; }
140    if( (hLdacBT->error_code_api = ldacBT_assert_mtu( mtu )) != LDACBT_ERR_NONE ){
141        return LDACBT_E_FAIL;
142    }
143    if( (hLdacBT->error_code_api = ldacBT_assert_eqmid( eqmid )) != LDACBT_ERR_NONE ){
144        return LDACBT_E_FAIL;
145    }
146    if( (hLdacBT->error_code_api = ldacBT_assert_cm( cm )) != LDACBT_ERR_NONE ){
147        return LDACBT_E_FAIL;
148    }
149    if( (hLdacBT->error_code_api = ldacBT_assert_sample_format( fmt )) != LDACBT_ERR_NONE ){
150        return LDACBT_E_FAIL;
151    }
152    if( (hLdacBT->error_code_api = ldacBT_assert_pcm_sampling_freq( sf )) != LDACBT_ERR_NONE ){
153        return LDACBT_E_FAIL;
154    }
155
156    ldacBT_close_handle( hLdacBT );
157
158    /* initialize handle for encode processing */
159    hLdacBT->proc_mode = LDACBT_PROCMODE_ENCODE;
160    hLdacBT->flg_encode_flushed = FALSE;
161
162    /* transport setting */
163    /* The ldac frame header is REQUIRED for A2DP streaming. */
164    hLdacBT->transport = TRUE;
165    hLdacBT->tx.mtu = mtu;
166    hLdacBT->tx.pkt_hdr_sz = LDACBT_TX_HEADER_SIZE;
167    hLdacBT->tx.tx_size = LDACBT_MTU_REQUIRED;
168    hLdacBT->tx.pkt_type = _2_DH5;
169    /* - BT TRANS HEADER etc */
170    hLdacBT->tx.tx_size -= hLdacBT->tx.pkt_hdr_sz;
171    if( hLdacBT->tx.tx_size > (hLdacBT->tx.mtu - hLdacBT->tx.pkt_hdr_sz) ){
172        /* never happen, mtu must be larger than LDACBT_MTU_REQUIRED(2DH5) */
173        hLdacBT->tx.tx_size = (hLdacBT->tx.mtu - hLdacBT->tx.pkt_hdr_sz);
174    }
175
176    /* channel configration */
177    cci = ldacBT_cm_to_cci(cm);
178    hLdacBT->cm = cm;
179    hLdacBT->cci = cci;
180    /* input pcm configuration */
181    hLdacBT->pcm.ch = a_cci_nch[cci];
182    hLdacBT->pcm.sf = sf;
183    hLdacBT->pcm.fmt = fmt;
184    switch(hLdacBT->pcm.fmt){
185      case LDACBT_SMPL_FMT_S16:
186        hLdacBT->pcm.wl = 2;
187        break;
188      case LDACBT_SMPL_FMT_S24:
189        hLdacBT->pcm.wl = 3;
190        break;
191      case LDACBT_SMPL_FMT_S32:
192      case LDACBT_SMPL_FMT_F32:
193        hLdacBT->pcm.wl = 4;
194        break;
195      default:
196        // must be rejected by ldacBT_assert_sample_format()
197        hLdacBT->pcm.wl = 4;
198        break;
199    }
200
201    /* initilize ldac encode */
202    /* Get sampling frequency index */
203    result = ldaclib_get_sampling_rate_index( hLdacBT->pcm.sf, &sfid );
204    if( LDAC_FAILED ( result ) ){
205        hLdacBT->error_code_api = LDACBT_ERR_ILL_SAMPLING_FREQ;
206        return LDACBT_E_FAIL;
207    }
208    hLdacBT->sfid = sfid;
209
210    /* Get number of frame samples */
211    result = ldaclib_get_frame_samples(sfid, &frame_samples);
212    if (LDAC_FAILED(result)) {
213        hLdacBT->error_code_api = LDACBT_ERR_ILL_SAMPLING_FREQ;
214        return LDACBT_E_FAIL;
215    }
216    hLdacBT->frm_samples = frame_samples;
217
218
219    /* Set Parameters by Encode Quality Mode Index */
220    hLdacBT->eqmid = eqmid;
221    /* get frame_length of EQMID */
222    pCfg = ldacBT_get_config( hLdacBT->eqmid, hLdacBT->tx.pkt_type );
223    /* set frame_length */
224    hLdacBT->frmlen_tx = hLdacBT->pcm.ch * pCfg->frmlen_1ch;
225    hLdacBT->frmlen = hLdacBT->frmlen_tx;
226    if (hLdacBT->transport) {
227        /* Adjust frame_length for Transport Header Data */
228        hLdacBT->frmlen -= LDACBT_FRMHDRBYTES;
229    }
230
231    /* Calculate how many LDAC frames fit into payload packet */
232    hLdacBT->tx.nfrm_in_pkt = hLdacBT->tx.tx_size / hLdacBT->frmlen_tx;
233
234
235    /* Get ldac encode setting */
236    result = ldaclib_get_encode_setting( pCfg->frmlen_1ch, sfid, &nbasebands, &grad_mode,
237                     &grad_qu_l, &grad_qu_h, &grad_ofst_l, &grad_ofst_h, &abc_flag);
238    if (LDAC_FAILED(result)) {
239        hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
240        return LDACBT_E_FAIL;
241    }
242
243    /* Set Configuration Information */
244    result = ldaclib_set_config_info( hLdacBT->hLDAC, hLdacBT->sfid, hLdacBT->cci,
245                                      hLdacBT->frmlen, hLdacBT->frm_status);
246    if (LDAC_FAILED(result)) {
247        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
248        return LDACBT_E_FAIL;
249    }
250    else if (result != LDAC_S_OK) {
251        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
252    }
253
254    /* Set Encoding Information */
255    result = ldaclib_set_encode_info(hLdacBT->hLDAC, nbasebands, grad_mode,
256                                     grad_qu_l, grad_qu_h, grad_ofst_l, grad_ofst_h, abc_flag);
257    if (LDAC_FAILED(result)) {
258        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
259        return LDACBT_E_FAIL;
260    }
261    else if (result != LDAC_S_OK) {
262        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
263    }
264
265    /* Initialize ldaclib for Encoding */
266    result = ldaclib_init_encode(hLdacBT->hLDAC);
267    if (LDAC_FAILED(result)) {
268        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
269        return LDACBT_E_FAIL;
270    }
271    else if (result != LDAC_S_OK) {
272        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
273    }
274
275    /* reset target eqmid as current setting */
276    hLdacBT->tgt_eqmid = hLdacBT->eqmid;
277    hLdacBT->tgt_nfrm_in_pkt = hLdacBT->tx.nfrm_in_pkt;
278    hLdacBT->tgt_frmlen = hLdacBT->frmlen;
279    hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
280
281    /* get bitrate */
282    hLdacBT->bitrate = ldacBT_frmlen_to_bitrate( hLdacBT->frmlen, hLdacBT->transport,
283                                                 hLdacBT->pcm.sf, hLdacBT->frm_samples );
284
285    return (hLdacBT->error_code_api==LDACBT_ERR_NONE?LDACBT_S_OK:LDACBT_E_FAIL);
286}
287
288/* Set Encode Quality Mode index */
289LDACBT_API int ldacBT_set_eqmid( HANDLE_LDAC_BT hLdacBT, int eqmid )
290{
291    if( hLdacBT == NULL ){
292        return LDACBT_E_FAIL;
293    }
294    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
295        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
296        return LDACBT_E_FAIL;
297    }
298
299    if( (hLdacBT->error_code_api = ldacBT_assert_eqmid( eqmid )) != LDACBT_ERR_NONE ){
300        return LDACBT_E_FAIL; /* fatal */
301    }
302	ldacBT_set_eqmid_core( hLdacBT, eqmid );
303
304	return LDACBT_S_OK;
305}
306
307/* Get Encode Quality Mode index */
308LDACBT_API int ldacBT_get_eqmid( HANDLE_LDAC_BT hLdacBT )
309{
310    if( hLdacBT == NULL ){
311        return LDACBT_E_FAIL;
312    }
313    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
314        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
315        return LDACBT_E_FAIL;
316    }
317    return hLdacBT->tgt_eqmid;
318}
319
320/* Alter encode quality mode index */
321LDACBT_API int  ldacBT_alter_eqmid_priority( HANDLE_LDAC_BT hLdacBT, int priority )
322{
323    int target_eqmid;
324    if( hLdacBT == NULL ){ return LDACBT_E_FAIL; }
325    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
326        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
327        return LDACBT_E_FAIL;
328    }
329    if( (priority != LDACBT_EQMID_INC_QUALITY) &&
330        (priority != LDACBT_EQMID_INC_CONNECTION )
331        ){
332            hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
333            return LDACBT_E_FAIL;
334    }
335
336    target_eqmid = ldacBT_get_altered_eqmid( hLdacBT,  priority);
337    if( target_eqmid < 0 ){
338        hLdacBT->error_code_api = LDACBT_ERR_ALTER_EQMID_LIMITED;
339        return LDACBT_E_FAIL;
340    }
341
342    ldacBT_set_eqmid_core( hLdacBT, target_eqmid );
343    return LDACBT_S_OK;
344}
345
346/* LDAC encode proccess */
347LDACBT_API int ldacBT_encode( HANDLE_LDAC_BT hLdacBT, void *p_pcm, int *pcm_used,
348                          unsigned char *p_stream, int *stream_sz, int *frame_num )
349{
350    LDAC_RESULT result;
351    LDACBT_SMPL_FMT_T fmt;
352    LDACBT_TRANSPORT_FRM_BUF *ptfbuf;
353    LDACBT_PCM_RING_BUF *ppcmring;
354    P_LDACBT_CONFIG pCfg;
355    int frmlen, frmlen_wrote, frmlen_adj;
356    int frm_status, flg_Do_Encode;
357    int nFrmToPkt, ch, wl;
358    unsigned char *p_ldac_transport_frame;
359    unsigned char a_frm_header[LDACBT_FRMHDRBYTES + 2];
360    if( hLdacBT == NULL ){
361        return LDACBT_E_FAIL;
362    }
363    if( hLdacBT->hLDAC == NULL ){
364        return LDACBT_E_FAIL;
365    }
366    if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ){
367        hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT;
368        return LDACBT_E_FAIL;
369    }
370    /* Clear Error Codes */
371    hLdacBT->error_code_api = LDACBT_ERR_NONE;
372    ldaclib_clear_error_code( hLdacBT->hLDAC );
373    ldaclib_clear_internal_error_code( hLdacBT->hLDAC );
374
375    if( ( pcm_used == NULL) ||
376        ( p_stream == NULL ) ||
377        ( stream_sz == NULL ) ||
378        ( frame_num == NULL )
379        ){
380            hLdacBT->error_code_api = LDACBT_ERR_ILL_PARAM;
381            return LDACBT_E_FAIL;
382    }
383    /* reset parameters */
384    *pcm_used = 0;
385    *stream_sz = 0;
386    *frame_num = 0;
387    flg_Do_Encode = 0;
388    fmt = hLdacBT->pcm.fmt;
389    ch = hLdacBT->pcm.ch;
390    wl = hLdacBT->pcm.wl;
391    ptfbuf = &hLdacBT->ldac_trns_frm_buf;
392    ppcmring = &hLdacBT->pcmring;
393
394    /* update input pcm data */
395    if( p_pcm != NULL ){
396        int nByteCpy, sz;
397        nByteCpy = LDACBT_ENC_LSU * wl * ch;
398        sz = ppcmring->nsmpl * wl * ch + nByteCpy;
399        if( sz < LDACBT_ENC_PCM_BUF_SZ ){
400            copy_data_ldac( p_pcm, ppcmring->buf + ppcmring->wp, nByteCpy );
401            ppcmring->wp += nByteCpy;
402            if( ppcmring->wp >= LDACBT_ENC_PCM_BUF_SZ ){
403                ppcmring->wp = 0;
404            }
405            ppcmring->nsmpl += LDACBT_ENC_LSU;
406            *pcm_used = nByteCpy;
407        }else{
408            /* Not enough space to copy.
409             * This will happen when the last encode process failed.
410             */
411            *pcm_used = 0;
412        }
413
414        if( ppcmring->nsmpl >= hLdacBT->frm_samples )
415        {
416            flg_Do_Encode = 1;
417        }
418    }else{
419        if (hLdacBT->flg_encode_flushed != TRUE){
420            flg_Do_Encode = 1;
421        }
422    }
423
424    if( !flg_Do_Encode ){
425        /* nothing to do */
426        return LDACBT_S_OK;
427    }
428
429    /* update frame_length if needed */
430    if( (hLdacBT->tgt_eqmid != UNSET) && (hLdacBT->tgt_eqmid != hLdacBT->eqmid) ){
431        if( ptfbuf->nfrm_in == 0 ){
432            ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
433            hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
434        }
435        else if( hLdacBT->tgt_nfrm_in_pkt > hLdacBT->tx.nfrm_in_pkt ){
436            /* for better connectivity, apply ASAP */
437            if( !hLdacBT->stat_alter_op ){
438                nFrmToPkt = hLdacBT->tgt_nfrm_in_pkt - ptfbuf->nfrm_in;
439                if( nFrmToPkt > 0 ){
440                    pCfg = ldacBT_get_config(LDACBT_EQMID_END, hLdacBT->tx.pkt_type);
441                    if( pCfg != NULL ){
442                        do{
443                            frmlen_adj = (hLdacBT->tx.tx_size - ptfbuf->used) / nFrmToPkt;
444                            if( frmlen_adj > hLdacBT->tgt_frmlen ) {
445                                frmlen_adj = hLdacBT->tgt_frmlen;
446                            }
447                            frmlen_adj -= LDACBT_FRMHDRBYTES;
448                            if( frmlen_adj >= pCfg->frmlen ){
449                                if( ldacBT_update_frmlen( hLdacBT, frmlen_adj ) == LDACBT_S_OK ){
450                                    hLdacBT->stat_alter_op = LDACBT_ALTER_OP__ACTIVE;
451                                    break;
452                                }
453                            }
454                        }while( --nFrmToPkt > 0 );
455                    }
456                    if( !hLdacBT->stat_alter_op ){
457                        /* force to flash streams */
458                        hLdacBT->stat_alter_op = LDACBT_ALTER_OP__FLASH;
459                    }
460                }
461            }
462        }
463        else{
464            /* wait the condition ptfbuf->nfrm_in == 0 for apply new frame_length */
465            hLdacBT->stat_alter_op = LDACBT_ALTER_OP__STANDBY;
466        }
467
468    }
469    else if( hLdacBT->tgt_frmlen != hLdacBT->frmlen ){
470        if( ptfbuf->nfrm_in == 0 ){
471            ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
472            hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
473        }else{
474            if( hLdacBT->tgt_nfrm_in_pkt == hLdacBT->tx.nfrm_in_pkt ){
475                ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
476                hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
477            }else{
478                if( hLdacBT->tgt_nfrm_in_pkt > hLdacBT->tx.nfrm_in_pkt ){
479                    /* for better connectivity, apply ASAP */
480                    if( !hLdacBT->stat_alter_op ){
481                        nFrmToPkt = hLdacBT->tgt_nfrm_in_pkt - ptfbuf->nfrm_in;
482                        if( nFrmToPkt > 0 ){
483                            frmlen_adj = (hLdacBT->tx.tx_size - ptfbuf->used) / nFrmToPkt;
484                            if( frmlen_adj > hLdacBT->tgt_frmlen ) {
485                                frmlen_adj = hLdacBT->tgt_frmlen;
486                            }
487                            if( ldacBT_update_frmlen( hLdacBT, frmlen_adj ) == LDACBT_S_OK ){
488                                hLdacBT->stat_alter_op = LDACBT_ALTER_OP__ACTIVE;
489                            }
490                            if( !hLdacBT->stat_alter_op ){
491                                /* flash streams */
492                                hLdacBT->stat_alter_op = LDACBT_ALTER_OP__FLASH;
493                            }
494                        }
495                    }
496                }else{
497                    /* wait the condition ptfbuf->nfrm_in == 0 for apply new frame_length */
498                    hLdacBT->stat_alter_op = LDACBT_ALTER_OP__STANDBY;
499                }
500            }
501        }
502    }
503
504    /* check write space for encoded data */
505    ldaclib_get_encode_frame_length( hLdacBT->hLDAC, &frmlen );
506
507    if( (( ptfbuf->used + frmlen + LDACBT_FRMHDRBYTES) > hLdacBT->tx.tx_size) ||
508        (hLdacBT->stat_alter_op == LDACBT_ALTER_OP__FLASH) || /* need to flash streams? */
509        (( ptfbuf->used + frmlen + LDACBT_FRMHDRBYTES) >= LDACBT_ENC_STREAM_BUF_SZ )
510        )
511    {
512        copy_data_ldac( ptfbuf->buf, p_stream, ptfbuf->used );
513        *stream_sz = ptfbuf->used;
514        *frame_num = ptfbuf->nfrm_in;
515        clear_data_ldac( ptfbuf->buf, sizeof(char)*LDACBT_ENC_STREAM_BUF_SZ);
516        ptfbuf->used = 0;
517        ptfbuf->nfrm_in = 0;
518        if( hLdacBT->stat_alter_op != LDACBT_ALTER_OP__NON ){
519            /* update frame length */
520            ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
521            hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
522        }
523    }
524    p_ldac_transport_frame = ptfbuf->buf + ptfbuf->used;
525
526    /* Encode Frame */
527    if( ppcmring->nsmpl > 0 ){
528        char *p_pcm_ring_r;
529        int nsmpl_to_clr;
530        nsmpl_to_clr = hLdacBT->frm_samples - ppcmring->nsmpl;
531        if( nsmpl_to_clr > 0 ){
532            int pos, nBytesToZero;
533            pos = ppcmring->rp + ppcmring->nsmpl * wl * ch;
534            nBytesToZero = nsmpl_to_clr * wl * ch;
535            while( nBytesToZero > 0 ){
536                int clearBytes;
537                clearBytes = nBytesToZero;
538                if ( pos + clearBytes >= LDACBT_ENC_PCM_BUF_SZ ){
539                    clearBytes = (LDACBT_ENC_PCM_BUF_SZ - pos);
540                }
541                clear_data_ldac( ppcmring->buf + pos, clearBytes);
542                nBytesToZero -= clearBytes;
543                if( (pos += clearBytes) >= LDACBT_ENC_PCM_BUF_SZ ){
544                    pos = 0;
545                }
546            }
547        }
548        p_pcm_ring_r = ppcmring->buf + ppcmring->rp;
549        ldacBT_prepare_pcm_encode( p_pcm_ring_r, hLdacBT->pp_pcm, hLdacBT->frm_samples, ch, fmt );
550        result = ldaclib_encode(hLdacBT->hLDAC, hLdacBT->pp_pcm, (LDAC_SMPL_FMT_T)fmt,
551                         p_ldac_transport_frame+LDACBT_FRMHDRBYTES, &frmlen_wrote);
552        if( !LDAC_FAILED(result) ){
553            ppcmring->rp += hLdacBT->frm_samples * wl * ch;
554            ppcmring->nsmpl -= hLdacBT->frm_samples;
555            if( ppcmring->rp >= LDACBT_ENC_PCM_BUF_SZ ){ ppcmring->rp = 0; }
556            if( ppcmring->nsmpl < 0 ){ ppcmring->nsmpl = 0; }
557        }
558    }else{
559        result = ldaclib_flush_encode(hLdacBT->hLDAC, (LDAC_SMPL_FMT_T)fmt,
560                             p_ldac_transport_frame+LDACBT_FRMHDRBYTES, &frmlen_wrote);
561        hLdacBT->flg_encode_flushed = TRUE;
562    }
563
564    if( LDAC_FAILED(result) ){
565        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
566        return LDACBT_E_FAIL;
567    }
568    else if( result != LDAC_S_OK ){
569        hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
570    }
571
572    if( frmlen_wrote > 0 ){
573        if( hLdacBT->transport == TRUE ){
574            /* Set Frame Header Data */
575            clear_data_ldac( a_frm_header, LDACBT_FRMHDRBYTES+2 );
576            /* Get Frame Header Information */
577            result = ldaclib_get_config_info(hLdacBT->hLDAC, &hLdacBT->sfid, &hLdacBT->cci,
578                            &frmlen, &frm_status);
579            if( LDAC_FAILED(result) ){
580                hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
581                return LDACBT_E_FAIL;
582            }
583            else if (result != LDAC_S_OK) {
584                hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
585            }
586
587            /* Set Frame Header */
588            result = ldaclib_set_frame_header(hLdacBT->hLDAC, a_frm_header, hLdacBT->sfid,
589                            hLdacBT->cci, frmlen, frm_status);
590            if( LDAC_FAILED(result) ){
591                hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
592                return LDACBT_E_FAIL;
593            }
594            else if (result != LDAC_S_OK) {
595                hLdacBT->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE;
596            }
597            copy_data_ldac( a_frm_header, p_ldac_transport_frame, LDACBT_FRMHDRBYTES );
598            frmlen_wrote += LDACBT_FRMHDRBYTES;
599        }
600        ptfbuf->used += frmlen_wrote;
601        ptfbuf->nfrm_in ++;
602    }
603
604    /* check for next frame buffer status */
605    if( *stream_sz == 0 ){
606        if( (( ptfbuf->used + frmlen_wrote) > hLdacBT->tx.tx_size) ||
607            (  ptfbuf->nfrm_in >= LDACBT_NFRM_TX_MAX ) ||
608            (( ptfbuf->used + frmlen_wrote) >= LDACBT_ENC_STREAM_BUF_SZ ) ||
609            ( p_pcm == NULL ) /* flush encode */
610            )
611        {
612            copy_data_ldac( ptfbuf->buf, p_stream, ptfbuf->used );
613            *stream_sz = ptfbuf->used;
614            *frame_num = ptfbuf->nfrm_in;
615            clear_data_ldac( ptfbuf->buf, sizeof(char)*LDACBT_ENC_STREAM_BUF_SZ);
616            ptfbuf->used = 0;
617            ptfbuf->nfrm_in = 0;
618            if( hLdacBT->stat_alter_op != LDACBT_ALTER_OP__NON ){
619                ldacBT_update_frmlen( hLdacBT, hLdacBT->tgt_frmlen );
620                hLdacBT->stat_alter_op = LDACBT_ALTER_OP__NON;
621            }
622        }
623    }
624
625    return LDACBT_S_OK;
626}
627