1 /*
2  * Copyright 2023 The Android Open Source Project
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 "mmc/codec_server/hfp_lc3_mmc_encoder.h"
18 
19 #include <bluetooth/log.h>
20 #include <lc3.h>
21 
22 #include <algorithm>
23 
24 #include "mmc/codec_server/lc3_utils.h"
25 #include "mmc/proto/mmc_config.pb.h"
26 #include "osi/include/allocator.h"
27 
28 namespace mmc {
29 
30 using namespace bluetooth;
31 
HfpLc3Encoder()32 HfpLc3Encoder::HfpLc3Encoder() : hfp_lc3_encoder_mem_(nullptr) {}
33 
~HfpLc3Encoder()34 HfpLc3Encoder::~HfpLc3Encoder() { cleanup(); }
35 
init(ConfigParam config)36 int HfpLc3Encoder::init(ConfigParam config) {
37   cleanup();
38 
39   if (!config.has_hfp_lc3_encoder_param()) {
40     log::error("HFP LC3 encoder params are not set");
41     return -EINVAL;
42   }
43 
44   param_ = config.hfp_lc3_encoder_param();
45   int dt_us = param_.dt_us();
46   int sr_hz = param_.sr_hz();
47   int sr_pcm_hz = param_.sr_pcm_hz();
48   const unsigned enc_size = lc3_encoder_size(dt_us, sr_pcm_hz);
49 
50   hfp_lc3_encoder_mem_ = osi_malloc(enc_size);
51 
52   hfp_lc3_encoder_ =
53       lc3_setup_encoder(dt_us, sr_hz, sr_pcm_hz, hfp_lc3_encoder_mem_);
54 
55   if (hfp_lc3_encoder_ == nullptr) {
56     log::error("Wrong parameters provided");
57     return -EINVAL;
58   }
59 
60   return HFP_LC3_PCM_BYTES;
61 }
62 
cleanup()63 void HfpLc3Encoder::cleanup() {
64   if (hfp_lc3_encoder_mem_) {
65     osi_free_and_reset((void**)&hfp_lc3_encoder_mem_);
66     log::info("Released the encoder instance");
67   }
68 }
69 
transcode(uint8_t * i_buf,int i_len,uint8_t * o_buf,int o_len)70 int HfpLc3Encoder::transcode(uint8_t* i_buf, int i_len, uint8_t* o_buf,
71                              int o_len) {
72   if (i_buf == nullptr || o_buf == nullptr) {
73     log::error("Buffer is null");
74     return -EINVAL;
75   }
76 
77   /* Note this only fails when wrong parameters are supplied. */
78   int rc = lc3_encode(hfp_lc3_encoder_, MapLc3PcmFmt(param_.fmt()), i_buf,
79                       param_.stride(), HFP_LC3_PKT_FRAME_LEN, o_buf);
80 
81   if (rc != 0) {
82     log::warn("Wrong encode parameters");
83     std::fill(o_buf, o_buf + o_len, 0);
84   }
85 
86   return HFP_LC3_PKT_FRAME_LEN;
87 }
88 
89 }  // namespace mmc
90