1 /******************************************************************************
2  *
3  * Copyright (c) 2023 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #pragma once
20 
21 #include <bluetooth/log.h>
22 #include <stdint.h>
23 
24 #include <vector>
25 
26 #include "audio_hal_client/audio_hal_client.h"
27 #include "le_audio_types.h"
28 
29 namespace bluetooth::le_audio {
30 
31 /* CodecInterface provides a thin abstraction layer above the codec instance. It
32  * manages the output buffers internally and resizes them automatically when
33  * needed.
34  * Multi-channel stream encoding requires multiple CodecInterface instances, but
35  * even then it is still possible to encode the stream data into a single output
36  * buffer. Thanks to the optional parameters to the encode() method, the
37  * internal buffer of the first instance can be used as an output buffer by the
38  * second instance, as long as equal life time of both instances is guaranteed.
39  *
40  */
41 class CodecInterface {
42  public:
43   enum class Status {
44     STATUS_ERR_CODEC_NOT_READY = -128,
45     STATUS_ERR_INVALID_CODEC_ID = -127,
46     STATUS_ERR_CODING_ERROR = -1,
47     STATUS_OK = 0,
48   };
49 
50   CodecInterface(const types::LeAudioCodecId& codec_id);
51   virtual ~CodecInterface();
CreateInstance(const types::LeAudioCodecId & codec_id)52   static std::unique_ptr<CodecInterface> CreateInstance(
53       const types::LeAudioCodecId& codec_id) {
54     return std::make_unique<CodecInterface>(codec_id);
55   }
56   virtual CodecInterface::Status InitEncoder(
57       const LeAudioCodecConfiguration& pcm_config,
58       const LeAudioCodecConfiguration& codec_config);
59   virtual CodecInterface::Status InitDecoder(
60       const LeAudioCodecConfiguration& codec_config,
61       const LeAudioCodecConfiguration& pcm_config);
62   virtual CodecInterface::Status Encode(
63       const uint8_t* data, int stride, uint16_t out_size,
64       std::vector<int16_t>* out_buffer = nullptr, uint16_t out_offset = 0);
65   virtual CodecInterface::Status Decode(uint8_t* data, uint16_t size);
66   virtual void Cleanup();
67   virtual bool IsReady();
68   virtual uint16_t GetNumOfSamplesPerChannel();
69   virtual uint8_t GetNumOfBytesPerSample();
70   virtual std::vector<int16_t>& GetDecodedSamples();
71 
72  private:
73   struct Impl;
74   Impl* impl;
75 };
76 
77 }  // namespace bluetooth::le_audio
78 
79 namespace fmt {
80 template <>
81 struct formatter<bluetooth::le_audio::CodecInterface::Status>
82     : enum_formatter<bluetooth::le_audio::CodecInterface::Status> {};
83 }  // namespace fmt
84