1 /*
2 * Copyright (c) 2013 - 2014, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #define LOG_TAG "audio_hw_compress"
21 /*#define LOG_NDEBUG 0*/
22 #define LOG_NDDEBUG 0
23
24 #include <errno.h>
25 #include <cutils/properties.h>
26 #include <stdlib.h>
27 #include <dlfcn.h>
28 #include <cutils/str_parms.h>
29 #include <cutils/log.h>
30
31 #include "audio_hw.h"
32 #include "platform.h"
33 #include "platform_api.h"
34
35 #include "sound/compress_params.h"
36 #include "sound/compress_offload.h"
37
38 #ifdef COMPRESS_CAPTURE_ENABLED
39
40 #define COMPRESS_IN_CONFIG_CHANNELS 1
41 #define COMPRESS_IN_CONFIG_PERIOD_SIZE 2048
42 #define COMPRESS_IN_CONFIG_PERIOD_COUNT 16
43
44
45 struct compress_in_module {
46 uint8_t *in_buf;
47 };
48
49 static struct compress_in_module c_in_mod = {
50 .in_buf = NULL,
51 };
52
53
audio_extn_compr_cap_init(struct stream_in * in)54 void audio_extn_compr_cap_init(struct stream_in *in)
55 {
56 in->usecase = USECASE_AUDIO_RECORD_COMPRESS;
57 in->config.channels = COMPRESS_IN_CONFIG_CHANNELS;
58 in->config.period_size = COMPRESS_IN_CONFIG_PERIOD_SIZE;
59 in->config.period_count= COMPRESS_IN_CONFIG_PERIOD_COUNT;
60 in->config.format = AUDIO_FORMAT_AMR_WB;
61 c_in_mod.in_buf = (uint8_t*)calloc(1, in->config.period_size*2);
62 }
63
audio_extn_compr_cap_deinit()64 void audio_extn_compr_cap_deinit()
65 {
66 if (c_in_mod.in_buf) {
67 free(c_in_mod.in_buf);
68 c_in_mod.in_buf = NULL;
69 }
70 }
71
audio_extn_compr_cap_enabled()72 bool audio_extn_compr_cap_enabled()
73 {
74 char prop_value[PROPERTY_VALUE_MAX] = {0};
75 bool tunnel_encode = false;
76
77 property_get("tunnel.audio.encode",prop_value,"0");
78 if (!strncmp("true", prop_value, sizeof("true")))
79 return true;
80 else
81 return false;
82 }
83
audio_extn_compr_cap_format_supported(audio_format_t format)84 bool audio_extn_compr_cap_format_supported(audio_format_t format)
85 {
86 if (format == AUDIO_FORMAT_AMR_WB)
87 return true;
88 else
89 return false;
90 }
91
92
audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase)93 bool audio_extn_compr_cap_usecase_supported(audio_usecase_t usecase)
94 {
95 if ((usecase == USECASE_AUDIO_RECORD_COMPRESS) ||
96 (usecase == USECASE_INCALL_REC_UPLINK_COMPRESS) ||
97 (usecase == USECASE_INCALL_REC_DOWNLINK_COMPRESS) ||
98 (usecase == USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS))
99 return true;
100 else
101 return false;
102 }
103
104
audio_extn_compr_cap_get_buffer_size(audio_format_t format)105 size_t audio_extn_compr_cap_get_buffer_size(audio_format_t format)
106 {
107 if (format == AUDIO_FORMAT_AMR_WB)
108 /*One AMR WB frame is 61 bytes. Return that to the caller.
109 The buffer size is not altered, that is still period size.*/
110 return AMR_WB_FRAMESIZE;
111 else
112 return 0;
113 }
114
audio_extn_compr_cap_read(struct stream_in * in,void * buffer,size_t bytes)115 size_t audio_extn_compr_cap_read(struct stream_in * in,
116 void *buffer, size_t bytes)
117 {
118 int ret;
119 struct snd_compr_audio_info *header;
120 uint32_t c_in_header;
121 uint32_t c_in_buf_size;
122
123 c_in_buf_size = in->config.period_size*2;
124
125 if (in->pcm) {
126 ret = pcm_read(in->pcm, c_in_mod.in_buf, c_in_buf_size);
127 if (ret < 0) {
128 ALOGE("pcm_read() returned failure: %d", ret);
129 return ret;
130 } else {
131 header = (struct snd_compr_audio_info *) c_in_mod.in_buf;
132 c_in_header = sizeof(*header) + header->reserved[0];
133 if (header->frame_size > 0) {
134 if (c_in_header + header->frame_size > c_in_buf_size) {
135 ALOGW("AMR WB read buffer overflow.");
136 header->frame_size =
137 bytes - sizeof(*header) - header->reserved[0];
138 }
139 ALOGV("c_in_buf: %p, data offset: %p, header size: %zu,"
140 "reserved[0]: %u frame_size: %d", c_in_mod.in_buf,
141 c_in_mod.in_buf + c_in_header,
142 sizeof(*header), header->reserved[0],
143 header->frame_size);
144 memcpy(buffer, c_in_mod.in_buf + c_in_header, header->frame_size);
145 } else {
146 ALOGE("pcm_read() with zero frame size");
147 ret = -EINVAL;
148 }
149 }
150 }
151
152 return 0;
153 }
154
155 #endif /* COMPRESS_CAPTURE_ENABLED end */
156