root/rat/trunk/channel.c @ 2765

Revision 2765, 12.0 KB (checked in by ucacoxh, 15 years ago)

- Consistency fixes for channel coder query functions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * FILE:      channel.c
3 * AUTHOR(S): Orion Hodson
4 *     
5 * $Revision$
6 * $Date$
7 *
8 * Copyright (c) 1999 University College London
9 * All rights reserved.
10 *
11 */
12#include "config_unix.h"
13#include "config_win32.h"
14
15#include "codec_types.h"
16#include "channel.h"
17#include "playout.h"
18#include "ts.h"
19#include "memory.h"
20#include "debug.h"
21
22typedef struct s_channel_state {
23        u_int16 coder;              /* Index of coder in coder table      */
24        u_char *state;              /* Pointer to state relevant to coder */
25        u_int32 state_len;          /* The size of that state             */
26        u_int8  units_per_packet:7; /* The number of units per packet     */
27        u_int8  is_encoder:1;       /* For debugging                      */
28} channel_state_t;
29
30typedef struct {
31        cc_details_t details;
32        u_int8  pt;
33        u_int8  layers;
34        int     (*enc_create_state)   (u_char                **state,
35                                       u_int32                *len);
36        void    (*enc_destroy_state)  (u_char                **state,
37                                       u_int32                 len);
38        int     (*enc_set_parameters) (u_char                 *state,
39                                       char                   *cmd);
40        int     (*enc_get_parameters) (u_char                 *state,
41                                       char                   *cmd,
42                                       u_int32                 cmd_len);
43        int     (*enc_reset)          (u_char                  *state);
44        int     (*enc_encode)         (u_char                  *state,
45                                       struct s_pb *in,
46                                       struct s_pb *out,
47                                       u_int32                  units_per_packet);
48        int     (*dec_create_state)   (u_char                 **state,
49                                       u_int32                 *len);
50        void    (*dec_destroy_state)  (u_char                 **state,
51                                       u_int32                  len);
52        int     (*dec_reset)          (u_char                  *state);
53        int     (*dec_decode)         (u_char                  *state,
54                                       struct s_pb *in,
55                                       struct s_pb *out,
56                                       ts_t                     now);
57        int     (*dec_peek)           (u_int8                   ccpt,
58                                       u_char                  *data,
59                                       u_int32                  len,
60                                       u_int16                 *upp,
61                                       u_int8                  *pt);
62        int     (*dec_describe)       (u_int8  pktpt,
63                                       u_char *data,
64                                       u_int32 data_len,
65                                       char   *outstr,
66                                       u_int32 out_len);
67} channel_coder_t;
68
69#include "cc_vanilla.h"
70#include "cc_rdncy.h"
71#include "cc_layered.h"
72
73#define CC_REDUNDANCY_PT 121
74#define CC_VANILLA_PT    255
75#define CC_LAYERED_PT    125
76
77#define CC_IDX_TO_ID(x) (((x)+1) | 0x0e00)
78#define CC_ID_TO_IDX(x) (((x)-1) & 0x000f)
79
80static const channel_coder_t table[] = {
81        /* The vanilla coder goes first. Update channel_get_null_coder
82         * and channel_coder_get_by_payload if it moves.
83         */
84        {
85                {
86                        CC_IDX_TO_ID(0),
87                        "None"
88                },
89                CC_VANILLA_PT,
90                1,
91                vanilla_encoder_create,
92                vanilla_encoder_destroy,
93                NULL,                   /* No parameters to set ...*/
94                NULL,                   /* ... or get. */
95                vanilla_encoder_reset,
96                vanilla_encoder_encode,
97                NULL,
98                NULL,
99                NULL,
100                vanilla_decoder_decode,
101                vanilla_decoder_peek,
102                vanilla_decoder_describe
103        },
104        {
105                {
106                        CC_IDX_TO_ID(1),
107                        "Redundancy"
108                },
109                CC_REDUNDANCY_PT,
110                1,
111                redundancy_encoder_create,
112                redundancy_encoder_destroy,
113                redundancy_encoder_set_parameters,
114                redundancy_encoder_get_parameters,
115                redundancy_encoder_reset,
116                redundancy_encoder_encode,
117                NULL,
118                NULL,
119                NULL,
120                redundancy_decoder_decode,
121                redundancy_decoder_peek,
122                redundancy_decoder_describe
123        },
124        {
125                {
126                        CC_IDX_TO_ID(2),
127                        "Layering"
128                },
129                CC_LAYERED_PT,
130                LAY_MAX_LAYERS,
131                layered_encoder_create,
132                layered_encoder_destroy,
133                layered_encoder_set_parameters,
134                layered_encoder_get_parameters,
135                layered_encoder_reset,
136                layered_encoder_encode,
137                NULL,
138                NULL,
139                NULL,
140                layered_decoder_decode,
141                layered_decoder_peek,
142                layered_decoder_describe
143        }
144};
145
146#define CC_NUM_CODERS (sizeof(table)/sizeof(table[0]))
147
148u_int32
149channel_get_coder_count()
150{
151        return (int)CC_NUM_CODERS;
152}
153
154const cc_details_t*
155channel_get_coder_details(u_int32 idx)
156{
157        if (idx < CC_NUM_CODERS) {
158                return &table[idx].details;
159        }
160        return NULL;
161}
162
163const cc_details_t*
164channel_get_coder_identity(channel_state_t *cs)
165{
166        assert(cs->coder < CC_NUM_CODERS);
167        return &table[cs->coder].details;
168}
169
170const cc_details_t*
171channel_get_null_coder(void)
172{
173        return &table[0].details;
174}
175
176/* The create, destroy, and reset functions take the same arguments and so use
177 * is_encoder to determine which function in the table to call.  It's dirty
178 * but it saves typing.  This should be undone at some time [oh]
179 */
180
181int
182_channel_coder_create(cc_id_t id, channel_state_t **ppcs, int is_encoder)
183{
184        channel_state_t *pcs;
185        int (*create_state)(u_char**, u_int32 *len);
186
187        pcs = (channel_state_t*)xmalloc(sizeof(channel_state_t));
188       
189        if (pcs == NULL) {
190                return FALSE;
191        }
192
193        *ppcs = pcs;
194
195        pcs->coder = (u_int16)CC_ID_TO_IDX(id);
196        assert(pcs->coder < CC_NUM_CODERS);
197
198        pcs->units_per_packet = 2;
199        pcs->is_encoder       = is_encoder;
200
201        if (is_encoder) {
202                create_state = table[pcs->coder].enc_create_state;
203        } else {
204                create_state = table[pcs->coder].dec_create_state;
205        }
206
207        if (create_state) {
208                create_state(&pcs->state, &pcs->state_len);
209        } else {
210                pcs->state     = NULL;
211                pcs->state_len = 0;
212        }
213
214        return TRUE;
215}
216
217void
218_channel_coder_destroy(channel_state_t **ppcs, int is_encoder)
219{
220        channel_state_t *pcs = *ppcs;
221
222        void (*destroy_state)(u_char**, u_int32);
223
224        assert(is_encoder == pcs->is_encoder);
225
226        if (is_encoder) {
227                destroy_state = table[pcs->coder].enc_destroy_state;
228        } else {
229                destroy_state = table[pcs->coder].dec_destroy_state;
230        }
231
232        if (destroy_state) {
233                destroy_state(&pcs->state, pcs->state_len);
234                pcs->state_len = 0;
235        }
236
237        assert(pcs->state     == NULL);
238        assert(pcs->state_len == 0);
239
240        xfree(pcs);
241        *ppcs = NULL;
242}
243
244int
245_channel_coder_reset(channel_state_t *pcs, int is_encoder)
246{
247        int (*reset) (u_char *state);
248       
249        assert(is_encoder == pcs->is_encoder);
250
251        if (is_encoder) {
252                reset = table[pcs->coder].enc_reset;
253        } else {
254                reset = table[pcs->coder].dec_reset;
255        }
256       
257        return (reset != NULL) ? reset(pcs->state) : TRUE;
258}
259
260/* Encoder specifics */
261
262int
263channel_encoder_set_units_per_packet(channel_state_t *cs, u_int16 units)
264{
265        /* This should not be hardcoded, it should be based on packet
266         *size [oth]
267         */
268        assert(cs->is_encoder);
269        if (units != 0 && units <= MAX_UNITS_PER_PACKET) {
270                cs->units_per_packet = (u_char)units;
271                return TRUE;
272        }
273        return FALSE;
274}
275
276u_int16
277channel_encoder_get_units_per_packet(channel_state_t *cs)
278{
279        assert(cs->is_encoder);
280        return cs->units_per_packet;
281}
282
283int
284channel_encoder_set_parameters(channel_state_t *cs, char *cmd)
285{
286        if (table[cs->coder].enc_set_parameters) {
287                return table[cs->coder].enc_set_parameters(cs->state, cmd);
288        }
289        return TRUE;
290}
291
292int
293channel_encoder_get_parameters(channel_state_t *cs, char *cmd, int cmd_len)
294{
295        if (table[cs->coder].enc_get_parameters) {
296                return table[cs->coder].enc_get_parameters(cs->state, cmd, cmd_len);
297        }
298        return TRUE;
299}
300
301int
302channel_encoder_encode(channel_state_t         *cs,
303                       struct s_pb *media_buffer,
304                       struct s_pb *channel_buffer)
305{
306        assert(table[cs->coder].enc_encode != NULL);
307        return table[cs->coder].enc_encode(cs->state, media_buffer, channel_buffer, cs->units_per_packet);
308}
309
310int
311channel_decoder_decode(channel_state_t         *cs,
312                       struct s_pb *media_buffer,
313                       struct s_pb *channel_buffer,
314                       ts_t                     now)
315{
316        assert(table[cs->coder].dec_decode != NULL);
317        return table[cs->coder].dec_decode(cs->state, media_buffer, channel_buffer, now);
318}
319
320int
321channel_decoder_matches(cc_id_t          id,
322                        channel_state_t *cs)
323{
324        u_int32 coder = CC_ID_TO_IDX(id);
325        return (coder == cs->coder);
326}
327
328int
329channel_verify_and_stat(cc_id_t  cid,
330                        u_int8   pktpt,
331                        u_char  *data,
332                        u_int32  data_len,
333                        u_int16 *units_per_packet,
334                        u_char  *codec_pt)
335{
336        u_int32 idx = CC_ID_TO_IDX(cid);
337        assert(idx < CC_NUM_CODERS);
338        return table[idx].dec_peek(pktpt, data, data_len, units_per_packet, codec_pt);
339}
340
341int 
342channel_describe_data(cc_id_t cid,
343                      u_int8  pktpt,
344                      u_char *data,
345                      u_int32 data_len,
346                      char *outstr,
347                      u_int32 out_len)
348{
349        u_int32 idx = CC_ID_TO_IDX(cid);
350        assert(idx < CC_NUM_CODERS);
351
352        assert(outstr  != NULL);
353        assert(out_len != 0);
354
355        if (table[idx].dec_describe) {
356                return (table[idx].dec_describe(pktpt, data, data_len, outstr, out_len-1));
357        }
358
359        strncpy(outstr, "Not implemented", out_len-1);
360        outstr[out_len-1] = '\0'; /* Always zero terminated */
361        return TRUE;
362}
363                                   
364cc_id_t
365channel_coder_get_by_payload(u_int8 payload)
366{
367        u_int32 i;
368
369        assert((payload & 0x80) == 0);
370
371        for(i = 0; i < CC_NUM_CODERS; i++) {
372                if (table[i].pt == payload) {
373                        return CC_IDX_TO_ID(i);
374                }
375        }
376        /* Return vanilla if not found */
377        return CC_IDX_TO_ID(0);       
378}
379
380u_int8
381channel_coder_get_payload(channel_state_t *st, u_int8 media_pt)
382{
383        assert(st->coder <= CC_NUM_CODERS);
384
385        if (table[st->coder].pt == CC_VANILLA_PT) {
386                return media_pt;
387        }
388        return table[st->coder].pt;
389}
390
391int
392channel_coder_exist_payload(u_int8 pt)
393{
394        u_int32 i;
395        for(i = 0; i < CC_NUM_CODERS; i++) {
396                if (table[i].pt == pt) {
397                        return TRUE;
398                }
399        }
400        return FALSE;       
401}
402
403u_int8
404channel_coder_get_layers(cc_id_t cid)
405{
406        u_int32 idx = CC_ID_TO_IDX(cid);
407        assert(idx < CC_NUM_CODERS);
408
409        return (table[idx].layers);
410}
Note: See TracBrowser for help on using the browser.