1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <netinet/in.h>
7 #include <sbc/sbc.h>
8 #include <syslog.h>
9
10 #include "cras_a2dp_info.h"
11 #include "cras_sbc_codec.h"
12 #include "cras_types.h"
13 #include "rtp.h"
14
init_a2dp(struct a2dp_info * a2dp,a2dp_sbc_t * sbc)15 int init_a2dp(struct a2dp_info *a2dp, a2dp_sbc_t *sbc)
16 {
17 uint8_t frequency = 0, mode = 0, subbands = 0, allocation, blocks = 0,
18 bitpool;
19
20 if (sbc->frequency & SBC_SAMPLING_FREQ_48000)
21 frequency = SBC_FREQ_48000;
22 else if (sbc->frequency & SBC_SAMPLING_FREQ_44100)
23 frequency = SBC_FREQ_44100;
24 else if (sbc->frequency & SBC_SAMPLING_FREQ_32000)
25 frequency = SBC_FREQ_32000;
26 else if (sbc->frequency & SBC_SAMPLING_FREQ_16000)
27 frequency = SBC_FREQ_16000;
28
29 if (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO)
30 mode = SBC_MODE_JOINT_STEREO;
31 else if (sbc->channel_mode & SBC_CHANNEL_MODE_STEREO)
32 mode = SBC_MODE_STEREO;
33 else if (sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL)
34 mode = SBC_MODE_DUAL_CHANNEL;
35 else if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO)
36 mode = SBC_MODE_MONO;
37
38 if (sbc->allocation_method & SBC_ALLOCATION_LOUDNESS)
39 allocation = SBC_AM_LOUDNESS;
40 else
41 allocation = SBC_AM_SNR;
42
43 switch (sbc->subbands) {
44 case SBC_SUBBANDS_4:
45 subbands = SBC_SB_4;
46 break;
47 case SBC_SUBBANDS_8:
48 subbands = SBC_SB_8;
49 break;
50 }
51
52 switch (sbc->block_length) {
53 case SBC_BLOCK_LENGTH_4:
54 blocks = SBC_BLK_4;
55 break;
56 case SBC_BLOCK_LENGTH_8:
57 blocks = SBC_BLK_8;
58 break;
59 case SBC_BLOCK_LENGTH_12:
60 blocks = SBC_BLK_12;
61 break;
62 case SBC_BLOCK_LENGTH_16:
63 blocks = SBC_BLK_16;
64 break;
65 }
66
67 bitpool = sbc->max_bitpool;
68
69 a2dp->codec = cras_sbc_codec_create(frequency, mode, subbands,
70 allocation, blocks, bitpool);
71 if (!a2dp->codec)
72 return -1;
73
74 /* SBC info */
75 a2dp->codesize = cras_sbc_get_codesize(a2dp->codec);
76 a2dp->frame_length = cras_sbc_get_frame_length(a2dp->codec);
77
78 a2dp->a2dp_buf_used = sizeof(struct rtp_header)
79 + sizeof(struct rtp_payload);
80 a2dp->frame_count = 0;
81 a2dp->seq_num = 0;
82 a2dp->samples = 0;
83
84 return 0;
85 }
86
destroy_a2dp(struct a2dp_info * a2dp)87 void destroy_a2dp(struct a2dp_info *a2dp)
88 {
89 cras_sbc_codec_destroy(a2dp->codec);
90 }
91
a2dp_codesize(struct a2dp_info * a2dp)92 int a2dp_codesize(struct a2dp_info *a2dp)
93 {
94 return a2dp->codesize;
95 }
96
a2dp_block_size(struct a2dp_info * a2dp,int a2dp_bytes)97 int a2dp_block_size(struct a2dp_info *a2dp, int a2dp_bytes)
98 {
99 return a2dp_bytes / a2dp->frame_length * a2dp->codesize;
100 }
101
a2dp_queued_frames(const struct a2dp_info * a2dp)102 int a2dp_queued_frames(const struct a2dp_info *a2dp)
103 {
104 return a2dp->samples;
105 }
106
a2dp_drain(struct a2dp_info * a2dp)107 void a2dp_drain(struct a2dp_info *a2dp)
108 {
109 a2dp->a2dp_buf_used = sizeof(struct rtp_header)
110 + sizeof(struct rtp_payload);
111 a2dp->samples = 0;
112 a2dp->seq_num = 0;
113 a2dp->frame_count = 0;
114 }
115
avdtp_write(int stream_fd,struct a2dp_info * a2dp)116 static int avdtp_write(int stream_fd, struct a2dp_info *a2dp)
117 {
118 int err, samples;
119 struct rtp_header *header;
120 struct rtp_payload *payload;
121
122 header = (struct rtp_header *)a2dp->a2dp_buf;
123 payload = (struct rtp_payload *)(a2dp->a2dp_buf + sizeof(*header));
124 memset(a2dp->a2dp_buf, 0, sizeof(*header) + sizeof(*payload));
125
126 payload->frame_count = a2dp->frame_count;
127 header->v = 2;
128 header->pt = 1;
129 header->sequence_number = htons(a2dp->seq_num);
130 header->timestamp = htonl(a2dp->nsamples);
131 header->ssrc = htonl(1);
132
133 err = send(stream_fd, a2dp->a2dp_buf, a2dp->a2dp_buf_used,
134 MSG_DONTWAIT);
135 if (err < 0)
136 return -errno;
137
138 /* Returns the number of samples in frame. */
139 samples = a2dp->samples;
140
141 /* Reset some data */
142 a2dp->a2dp_buf_used = sizeof(*header) + sizeof(*payload);
143 a2dp->frame_count = 0;
144 a2dp->samples = 0;
145 a2dp->seq_num++;
146
147 return samples;
148 }
149
a2dp_encode(struct a2dp_info * a2dp,const void * pcm_buf,int pcm_buf_size,int format_bytes,size_t link_mtu)150 int a2dp_encode(struct a2dp_info *a2dp, const void *pcm_buf, int pcm_buf_size,
151 int format_bytes, size_t link_mtu)
152 {
153 int processed;
154 size_t out_encoded;
155
156 if (link_mtu > A2DP_BUF_SIZE_BYTES)
157 link_mtu = A2DP_BUF_SIZE_BYTES;
158 if (link_mtu == a2dp->a2dp_buf_used)
159 return 0;
160
161 processed = a2dp->codec->encode(a2dp->codec, pcm_buf, pcm_buf_size,
162 a2dp->a2dp_buf + a2dp->a2dp_buf_used,
163 link_mtu - a2dp->a2dp_buf_used,
164 &out_encoded);
165 if (processed < 0) {
166 syslog(LOG_ERR, "a2dp encode error %d", processed);
167 return processed;
168 }
169
170 if (a2dp->codesize > 0)
171 a2dp->frame_count += processed / a2dp->codesize;
172 a2dp->a2dp_buf_used += out_encoded;
173
174 a2dp->samples += processed / format_bytes;
175 a2dp->nsamples += processed / format_bytes;
176
177 return processed;
178 }
179
a2dp_write(struct a2dp_info * a2dp,int stream_fd,size_t link_mtu)180 int a2dp_write(struct a2dp_info *a2dp, int stream_fd, size_t link_mtu)
181 {
182 /* Do avdtp write when the max number of SBC frames is reached. */
183 if (a2dp->a2dp_buf_used + a2dp->frame_length >
184 link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload))
185 return avdtp_write(stream_fd, a2dp);
186
187 return 0;
188 }
189