1 /*
2  * Copyright 2008-2014 Arsen Chaloyan
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  * $Id: mpf_codec_descriptor.h 2239 2014-11-12 01:52:59Z achaloyan@gmail.com $
17  */
18 
19 #ifndef MPF_CODEC_DESCRIPTOR_H
20 #define MPF_CODEC_DESCRIPTOR_H
21 
22 /**
23  * @file mpf_codec_descriptor.h
24  * @brief MPF Codec Descriptor
25  */
26 
27 #include <apr_tables.h>
28 #include "apt_string.h"
29 #include "mpf.h"
30 
31 APT_BEGIN_EXTERN_C
32 
33 /** Codec frame time base in msec */
34 #define CODEC_FRAME_TIME_BASE 10
35 /** Bytes per sample for linear pcm */
36 #define BYTES_PER_SAMPLE 2
37 /** Bits per sample for linear pcm */
38 #define BITS_PER_SAMPLE 16
39 
40 /** Supported sampling rates */
41 typedef enum {
42 	MPF_SAMPLE_RATE_NONE  = 0x00,
43 	MPF_SAMPLE_RATE_8000  = 0x01,
44 	MPF_SAMPLE_RATE_16000 = 0x02,
45 	MPF_SAMPLE_RATE_32000 = 0x04,
46 	MPF_SAMPLE_RATE_48000 = 0x08,
47 
48 	MPF_SAMPLE_RATE_SUPPORTED =	MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 |
49 								MPF_SAMPLE_RATE_32000 | MPF_SAMPLE_RATE_48000
50 } mpf_sample_rates_e;
51 
52 /** Codec descriptor declaration */
53 typedef struct mpf_codec_descriptor_t mpf_codec_descriptor_t;
54 /** Codec attributes declaration */
55 typedef struct mpf_codec_attribs_t mpf_codec_attribs_t;
56 /** Codec list declaration */
57 typedef struct mpf_codec_list_t mpf_codec_list_t;
58 /** Codec capabilities declaration */
59 typedef struct mpf_codec_capabilities_t mpf_codec_capabilities_t;
60 /** Codec frame declaration */
61 typedef struct mpf_codec_frame_t mpf_codec_frame_t;
62 
63 
64 /** Codec descriptor */
65 struct mpf_codec_descriptor_t {
66 	/** Payload type used in RTP packet */
67 	apr_byte_t   payload_type;
68 	/** Codec name */
69 	apt_str_t    name;
70 	/** Sampling rate */
71 	apr_uint16_t sampling_rate;
72 	/** Channel count */
73 	apr_byte_t   channel_count;
74 	/** Codec dependent additional format */
75 	apt_str_t    format;
76 	/**  Enabled/disabled state */
77 	apt_bool_t   enabled;
78 };
79 
80 /** List of codec descriptors */
81 struct mpf_codec_list_t {
82 	/** Dynamic array of codec descriptors (mpf_codec_descriptor_t) */
83 	apr_array_header_t     *descriptor_arr;
84 	/** Preffered primary (audio/video codec) descriptor from descriptor_arr */
85 	mpf_codec_descriptor_t *primary_descriptor;
86 	/** Preffered named event (telephone-event) descriptor from descriptor_arr */
87 	mpf_codec_descriptor_t *event_descriptor;
88 };
89 
90 /** Codec attributes */
91 struct mpf_codec_attribs_t {
92 	/** Codec name */
93 	apt_str_t  name;
94 	/** Bits per sample */
95 	apr_byte_t bits_per_sample;
96 	/** Supported sampling rates (mpf_sample_rates_e) */
97 	int        sample_rates;
98 };
99 
100 /** List of codec attributes (capabilities) */
101 struct mpf_codec_capabilities_t {
102 	/** Dynamic array of codec attributes (mpf_codec_attrribs_t) */
103 	apr_array_header_t *attrib_arr;
104 	/** Allow/support named events */
105 	apt_bool_t          allow_named_events;
106 };
107 
108 /** Codec frame */
109 struct mpf_codec_frame_t {
110 	/** Raw buffer, which may contain encoded or decoded data */
111 	void      *buffer;
112 	/** Buffer size */
113 	apr_size_t size;
114 };
115 
116 
117 /** Initialize codec descriptor */
mpf_codec_descriptor_init(mpf_codec_descriptor_t * descriptor)118 static APR_INLINE void mpf_codec_descriptor_init(mpf_codec_descriptor_t *descriptor)
119 {
120 	descriptor->payload_type = 0;
121 	apt_string_reset(&descriptor->name);
122 	descriptor->sampling_rate = 0;
123 	descriptor->channel_count = 0;
124 	apt_string_reset(&descriptor->format);
125 	descriptor->enabled = TRUE;
126 }
127 
128 /** Initialize codec descriptor */
mpf_codec_descriptor_create(apr_pool_t * pool)129 static APR_INLINE  mpf_codec_descriptor_t* mpf_codec_descriptor_create(apr_pool_t *pool)
130 {
131 	mpf_codec_descriptor_t *descriptor = (mpf_codec_descriptor_t*) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
132 	mpf_codec_descriptor_init(descriptor);
133 	return descriptor;
134 }
135 
136 /** Calculate encoded frame size in bytes */
mpf_codec_frame_size_calculate(const mpf_codec_descriptor_t * descriptor,const mpf_codec_attribs_t * attribs)137 static APR_INLINE apr_size_t mpf_codec_frame_size_calculate(const mpf_codec_descriptor_t *descriptor, const mpf_codec_attribs_t *attribs)
138 {
139 	return (size_t) descriptor->channel_count * attribs->bits_per_sample * CODEC_FRAME_TIME_BASE *
140 			descriptor->sampling_rate / 1000 / 8; /* 1000 - msec per sec, 8 - bits per byte */
141 }
142 
143 /** Calculate samples of the frame (ts) */
mpf_codec_frame_samples_calculate(const mpf_codec_descriptor_t * descriptor)144 static APR_INLINE apr_size_t mpf_codec_frame_samples_calculate(const mpf_codec_descriptor_t *descriptor)
145 {
146 	return (size_t) descriptor->channel_count * CODEC_FRAME_TIME_BASE * descriptor->sampling_rate / 1000;
147 }
148 
149 /** Calculate linear frame size in bytes */
mpf_codec_linear_frame_size_calculate(apr_uint16_t sampling_rate,apr_byte_t channel_count)150 static APR_INLINE apr_size_t mpf_codec_linear_frame_size_calculate(apr_uint16_t sampling_rate, apr_byte_t channel_count)
151 {
152 	return (size_t) channel_count * BYTES_PER_SAMPLE * CODEC_FRAME_TIME_BASE * sampling_rate / 1000;
153 }
154 
155 
156 
157 /** Reset list of codec descriptors */
mpf_codec_list_reset(mpf_codec_list_t * codec_list)158 static APR_INLINE void mpf_codec_list_reset(mpf_codec_list_t *codec_list)
159 {
160 	codec_list->descriptor_arr = NULL;
161 	codec_list->primary_descriptor = NULL;
162 	codec_list->event_descriptor = NULL;
163 }
164 
165 /** Initialize list of codec descriptors */
mpf_codec_list_init(mpf_codec_list_t * codec_list,apr_size_t initial_count,apr_pool_t * pool)166 static APR_INLINE void mpf_codec_list_init(mpf_codec_list_t *codec_list, apr_size_t initial_count, apr_pool_t *pool)
167 {
168 	codec_list->descriptor_arr = apr_array_make(pool,(int)initial_count, sizeof(mpf_codec_descriptor_t));
169 	codec_list->primary_descriptor = NULL;
170 	codec_list->event_descriptor = NULL;
171 }
172 
173 /** Copy list of codec descriptors */
mpf_codec_list_copy(mpf_codec_list_t * codec_list,const mpf_codec_list_t * src_codec_list,apr_pool_t * pool)174 static APR_INLINE void mpf_codec_list_copy(mpf_codec_list_t *codec_list, const mpf_codec_list_t *src_codec_list, apr_pool_t *pool)
175 {
176 	codec_list->descriptor_arr = apr_array_copy(pool,src_codec_list->descriptor_arr);
177 }
178 
179 /** Increment number of codec descriptors in the list and return the descriptor to fill */
mpf_codec_list_add(mpf_codec_list_t * codec_list)180 static APR_INLINE mpf_codec_descriptor_t* mpf_codec_list_add(mpf_codec_list_t *codec_list)
181 {
182 	mpf_codec_descriptor_t *descriptor = (mpf_codec_descriptor_t*)apr_array_push(codec_list->descriptor_arr);
183 	mpf_codec_descriptor_init(descriptor);
184 	return descriptor;
185 }
186 
187 /** Determine if codec list is empty */
mpf_codec_list_is_empty(const mpf_codec_list_t * codec_list)188 static APR_INLINE apt_bool_t mpf_codec_list_is_empty(const mpf_codec_list_t *codec_list)
189 {
190 	return apr_is_empty_array(codec_list->descriptor_arr);
191 }
192 
193 /** Get codec descriptor by index */
mpf_codec_list_descriptor_get(const mpf_codec_list_t * codec_list,apr_size_t id)194 static APR_INLINE mpf_codec_descriptor_t* mpf_codec_list_descriptor_get(const mpf_codec_list_t *codec_list, apr_size_t id)
195 {
196 	if(id >= (apr_size_t)codec_list->descriptor_arr->nelts) {
197 		return NULL;
198 	}
199 	return &APR_ARRAY_IDX(codec_list->descriptor_arr,id,mpf_codec_descriptor_t);
200 }
201 
202 /** Create linear PCM descriptor */
203 MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_lpcm_descriptor_create(apr_uint16_t sampling_rate, apr_byte_t channel_count, apr_pool_t *pool);
204 
205 /** Create codec descriptor by capabilities */
206 MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_descriptor_create_by_capabilities(const mpf_codec_capabilities_t *capabilities, const mpf_codec_descriptor_t *peer, apr_pool_t *pool);
207 
208 /** Match two codec descriptors */
209 MPF_DECLARE(apt_bool_t) mpf_codec_descriptors_match(const mpf_codec_descriptor_t *descriptor1, const mpf_codec_descriptor_t *descriptor2);
210 
211 /** Match specified codec descriptor and the default lpcm one */
212 MPF_DECLARE(apt_bool_t) mpf_codec_lpcm_descriptor_match(const mpf_codec_descriptor_t *descriptor);
213 
214 /** Match codec descriptor by attribs specified */
215 MPF_DECLARE(apt_bool_t) mpf_codec_descriptor_match_by_attribs(mpf_codec_descriptor_t *descriptor, const mpf_codec_descriptor_t *static_descriptor, const mpf_codec_attribs_t *attribs);
216 
217 
218 
219 /** Initialize codec capabilities */
mpf_codec_capabilities_init(mpf_codec_capabilities_t * capabilities,apr_size_t initial_count,apr_pool_t * pool)220 static APR_INLINE void mpf_codec_capabilities_init(mpf_codec_capabilities_t *capabilities, apr_size_t initial_count, apr_pool_t *pool)
221 {
222 	capabilities->attrib_arr = apr_array_make(pool,(int)initial_count, sizeof(mpf_codec_attribs_t));
223 	capabilities->allow_named_events = TRUE;
224 }
225 
226 /** Clone codec capabilities */
mpf_codec_capabilities_clone(mpf_codec_capabilities_t * capabilities,const mpf_codec_capabilities_t * src_capabilities,apr_pool_t * pool)227 static APR_INLINE void mpf_codec_capabilities_clone(mpf_codec_capabilities_t *capabilities, const mpf_codec_capabilities_t *src_capabilities, apr_pool_t *pool)
228 {
229 	capabilities->attrib_arr = apr_array_copy(pool,src_capabilities->attrib_arr);
230 	capabilities->allow_named_events = src_capabilities->allow_named_events;
231 }
232 
233 /** Merge codec capabilities */
mpf_codec_capabilities_merge(mpf_codec_capabilities_t * capabilities,const mpf_codec_capabilities_t * src_capabilities,apr_pool_t * pool)234 static APR_INLINE apt_bool_t mpf_codec_capabilities_merge(mpf_codec_capabilities_t *capabilities, const mpf_codec_capabilities_t *src_capabilities, apr_pool_t *pool)
235 {
236 	if(capabilities->allow_named_events == FALSE && src_capabilities->allow_named_events == TRUE) {
237 		capabilities->allow_named_events = src_capabilities->allow_named_events;
238 	}
239 	capabilities->attrib_arr = apr_array_append(pool,capabilities->attrib_arr,src_capabilities->attrib_arr);
240 	return TRUE;
241 }
242 
243 /** Add codec capabilities */
mpf_codec_capabilities_add(mpf_codec_capabilities_t * capabilities,int sample_rates,const char * codec_name)244 static APR_INLINE apt_bool_t mpf_codec_capabilities_add(mpf_codec_capabilities_t *capabilities, int sample_rates, const char *codec_name)
245 {
246 	mpf_codec_attribs_t *attribs = (mpf_codec_attribs_t*)apr_array_push(capabilities->attrib_arr);
247 	apt_string_assign(&attribs->name,codec_name,capabilities->attrib_arr->pool);
248 	attribs->sample_rates = sample_rates;
249 	attribs->bits_per_sample = 0;
250 	return TRUE;
251 }
252 
253 /** Add default (linear PCM) capabilities */
254 MPF_DECLARE(apt_bool_t) mpf_codec_default_capabilities_add(mpf_codec_capabilities_t *capabilities);
255 
256 /** Validate codec capabilities */
mpf_codec_capabilities_validate(mpf_codec_capabilities_t * capabilities)257 static APR_INLINE apt_bool_t mpf_codec_capabilities_validate(mpf_codec_capabilities_t *capabilities)
258 {
259 	if(apr_is_empty_array(capabilities->attrib_arr) == TRUE) {
260 		mpf_codec_default_capabilities_add(capabilities);
261 	}
262 	return TRUE;
263 }
264 
265 
266 
267 /** Find matched descriptor in codec list */
268 MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_list_descriptor_find(const mpf_codec_list_t *codec_list, const mpf_codec_descriptor_t *descriptor);
269 
270 /** Match codec list with specified capabilities */
271 MPF_DECLARE(apt_bool_t) mpf_codec_list_match(mpf_codec_list_t *codec_list, const mpf_codec_capabilities_t *capabilities);
272 
273 /** Intersect two codec lists */
274 MPF_DECLARE(apt_bool_t) mpf_codec_lists_intersect(mpf_codec_list_t *codec_list1, mpf_codec_list_t *codec_list2);
275 
276 
277 /** Get sampling rate mask (mpf_sample_rate_e) by integer value  */
278 MPF_DECLARE(int) mpf_sample_rate_mask_get(apr_uint16_t sampling_rate);
279 
280 
281 APT_END_EXTERN_C
282 
283 #endif /* MPF_CODEC_DESCRIPTOR_H */
284