~ubuntu-branches/ubuntu/intrepid/gpac/intrepid-proposed

« back to all changes in this revision

Viewing changes to modules/saf_in/saf_in.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2007-01-24 23:34:57 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070124233457-zzlls8afkt0nyakj
Tags: 0.4.2~rc2-0ubuntu1
* New upstream release
  * Most notably MP4 tagging support via MP4Box -itags
* debian/patches/01_64bits.dpatch: dropped; included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *                      GPAC - Multimedia Framework C SDK
 
3
 *
 
4
 *                      Authors: Jean le Feuvre
 
5
 *                              Copyright (c) 2005-200X ENST
 
6
 *                                      All rights reserved
 
7
 *
 
8
 *  This file is part of GPAC / SAF reader module
 
9
 *
 
10
 *  GPAC is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU Lesser General Public License as published by
 
12
 *  the Free Software Foundation; either version 2, or (at your option)
 
13
 *  any later version.
 
14
 *   
 
15
 *  GPAC is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU Lesser General Public License for more details.
 
19
 *   
 
20
 *  You should have received a copy of the GNU Lesser General Public
 
21
 *  License along with this library; see the file COPYING.  If not, write to
 
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 
23
 *              
 
24
 */
 
25
 
 
26
#include <gpac/modules/service.h>
 
27
#include <gpac/modules/codec.h>
 
28
#include <gpac/constants.h>
 
29
#include <gpac/thread.h>
 
30
 
 
31
typedef struct
 
32
{
 
33
        LPNETCHANNEL ch;
 
34
        u32 au_sn, stream_id, ts_res, buffer_min;
 
35
        GF_ESD *esd;
 
36
} SAFChannel;
 
37
 
 
38
enum
 
39
{
 
40
        SAF_FILE_LOCAL,
 
41
        SAF_FILE_REMOTE,
 
42
        SAF_LIVE_STREAM
 
43
};
 
44
 
 
45
typedef struct
 
46
{
 
47
        GF_ClientService *service;
 
48
        GF_List *channels;
 
49
        Bool needs_connection;
 
50
 
 
51
        u32 saf_type;
 
52
 
 
53
        /*file downloader*/
 
54
        GF_DownloadSession * dnload;
 
55
 
 
56
        /*SAF buffer for both lcoal, remote and live streams*/
 
57
        char *saf_data;
 
58
        u32 saf_size, alloc_size;
 
59
 
 
60
        /*local file playing*/
 
61
        GF_Thread *th;
 
62
        FILE *stream;
 
63
        u32 run_state;
 
64
        u32 start_range, end_range;
 
65
        Double duration;
 
66
        u32 nb_playing;
 
67
} SAFIn;
 
68
 
 
69
static GFINLINE SAFChannel *saf_get_channel(SAFIn *saf, u32 stream_id, LPNETCHANNEL a_ch)
 
70
{
 
71
        SAFChannel *ch;
 
72
        u32 i=0;
 
73
        while ((ch=gf_list_enum(saf->channels, &i))) {
 
74
                if (ch->stream_id==stream_id) return ch;
 
75
                if (a_ch && (ch->ch==a_ch)) return ch;
 
76
        }
 
77
        return NULL;
 
78
}
 
79
 
 
80
static Bool SAF_CanHandleURL(GF_InputService *plug, const char *url)
 
81
{
 
82
        char *sExt;
 
83
        sExt = strrchr(url, '.');
 
84
        if (!sExt) return 0;
 
85
        if (gf_term_check_extension(plug, "application/x-saf", "saf lsr", "SAF Rich Media", sExt)) return 1;
 
86
        return 0;
 
87
}
 
88
 
 
89
static void SAF_Regulate(SAFIn *read)
 
90
{
 
91
        GF_NetworkCommand com;
 
92
        SAFChannel *ch;
 
93
 
 
94
        com.command_type = GF_NET_CHAN_BUFFER_QUERY;
 
95
        /*sleep untill the buffer occupancy is too low - note that this work because all streams in this
 
96
        demuxer are synchronized*/
 
97
        while (read->run_state) {
 
98
                u32 min_occ = (u32) -1;
 
99
                u32 i=0;
 
100
                while ( (ch=gf_list_enum(read->channels, &i))) {
 
101
                        com.base.on_channel = ch->ch;
 
102
                        gf_term_on_command(read->service, &com, GF_OK);
 
103
                        if (com.buffer.occupancy < ch->buffer_min) return;
 
104
                        if (com.buffer.occupancy) min_occ = MIN(min_occ, com.buffer.occupancy - ch->buffer_min);
 
105
                }
 
106
                if (min_occ == (u32) -1) break;
 
107
                //fprintf(stdout, "Regulating SAF demux - sleeping for %d ms\n", min_occ);
 
108
                gf_sleep(min_occ);
 
109
        }
 
110
}
 
111
 
 
112
static void SAF_OnData(void *cbk, char *data, u32 size, u32 status, GF_Err e)
 
113
{
 
114
        Bool is_rap, go;
 
115
        SAFChannel *ch;
 
116
        u32 cts, au_sn, au_size, bs_pos, type, i, stream_id;
 
117
        GF_BitStream *bs;
 
118
        GF_SLHeader sl_hdr;
 
119
        
 
120
        SAFIn *read = (SAFIn *) cbk;
 
121
 
 
122
        /*done*/
 
123
        if ((e == GF_EOS) && read->stream) {
 
124
                if (read->saf_type==SAF_FILE_REMOTE) read->saf_type = SAF_FILE_LOCAL;
 
125
                return;
 
126
        }
 
127
        /*handle service message*/
 
128
        if (read->dnload) {
 
129
                gf_term_download_update_stats(read->dnload);
 
130
                if (read->needs_connection) {
 
131
                        u32 total_size;
 
132
                        gf_dm_sess_get_stats(read->dnload, NULL, NULL, &total_size, NULL, NULL, NULL);
 
133
                        if (!total_size) read->saf_type = SAF_LIVE_STREAM;
 
134
                }
 
135
        }
 
136
        if (!size) return;
 
137
 
 
138
        if (e<0) {
 
139
                if (read->needs_connection) {
 
140
                        read->needs_connection = 0;
 
141
                        gf_term_on_connect(read->service, NULL, e);
 
142
                }
 
143
                return;
 
144
        }
 
145
        if (!read->run_state) return;
 
146
 
 
147
        if (read->alloc_size < read->saf_size+size) {
 
148
                read->saf_data = realloc(read->saf_data, sizeof(char)*(read->saf_size+size) );
 
149
                read->alloc_size = read->saf_size+size;
 
150
        }
 
151
        memcpy(read->saf_data + read->saf_size, data, sizeof(char)*size);
 
152
        read->saf_size+=size;
 
153
 
 
154
        /*first AU not complete yet*/
 
155
        if (read->saf_size<10) return;
 
156
 
 
157
        bs = gf_bs_new(read->saf_data, read->saf_size, GF_BITSTREAM_READ);
 
158
        bs_pos = 0;
 
159
 
 
160
        go = 1;
 
161
        while (go) {
 
162
                u32 avail = (u32) gf_bs_available(bs);
 
163
                bs_pos = (u32) gf_bs_get_position(bs);
 
164
 
 
165
                if (avail<10) break;
 
166
 
 
167
                is_rap = gf_bs_read_int(bs, 1);
 
168
                au_sn = gf_bs_read_int(bs, 15);
 
169
                gf_bs_read_int(bs, 2);
 
170
                cts = gf_bs_read_int(bs, 30);
 
171
                au_size = gf_bs_read_int(bs, 16);
 
172
                avail-=8;
 
173
 
 
174
                if (au_size > avail) break;
 
175
                assert(au_size>=2);
 
176
 
 
177
                is_rap = 1;
 
178
 
 
179
                type = gf_bs_read_int(bs, 4);
 
180
                stream_id = gf_bs_read_int(bs, 12);
 
181
                au_size -= 2;
 
182
 
 
183
                ch = saf_get_channel(read, stream_id, NULL);
 
184
                switch (type) {
 
185
                case 1:
 
186
                case 2:
 
187
                case 7:
 
188
                        if (ch) {
 
189
                                gf_bs_skip_bytes(bs, au_size);
 
190
                        } else {
 
191
                                SAFChannel *first = gf_list_get(read->channels, 0);
 
192
                                GF_SAFEALLOC(ch, sizeof(SAFChannel));
 
193
                                ch->stream_id = stream_id;
 
194
                                ch->esd = gf_odf_desc_esd_new(0);
 
195
                                ch->esd->ESID = stream_id;
 
196
                                ch->esd->OCRESID = first ? first->stream_id : stream_id;
 
197
                                ch->esd->slConfig->useRandomAccessPointFlag = 1;
 
198
                                ch->esd->slConfig->AUSeqNumLength = 0;
 
199
                                ch->esd->decoderConfig->objectTypeIndication = gf_bs_read_u8(bs);
 
200
                                ch->esd->decoderConfig->streamType = gf_bs_read_u8(bs);
 
201
                                ch->ts_res = ch->esd->slConfig->timestampResolution = gf_bs_read_u24(bs);
 
202
                                ch->esd->decoderConfig->bufferSizeDB = gf_bs_read_u16(bs);
 
203
                                au_size -= 7;
 
204
                                if ((ch->esd->decoderConfig->objectTypeIndication == 0xFF) && (ch->esd->decoderConfig->streamType == 0xFF) ) {
 
205
                                        u16 mimeLen = gf_bs_read_u16(bs);
 
206
                                        gf_bs_skip_bytes(bs, mimeLen);
 
207
                                        au_size -= mimeLen+2;
 
208
                                }
 
209
                                if (type==7) {
 
210
                                        u16 urlLen = gf_bs_read_u16(bs);
 
211
                                        ch->esd->URLString = malloc(sizeof(char)*(urlLen+1));
 
212
                                        gf_bs_read_data(bs, ch->esd->URLString, urlLen);
 
213
                                        ch->esd->URLString[urlLen] = 0;
 
214
                                        au_size -= urlLen+2;
 
215
                                }
 
216
                                if (au_size) {
 
217
                                        ch->esd->decoderConfig->decoderSpecificInfo->dataLength = au_size;
 
218
                                        ch->esd->decoderConfig->decoderSpecificInfo->data = malloc(sizeof(char)*au_size);
 
219
                                        gf_bs_read_data(bs, ch->esd->decoderConfig->decoderSpecificInfo->data, au_size);
 
220
                                }
 
221
                                if (ch->esd->decoderConfig->streamType==4) ch->buffer_min=100;
 
222
                                else if (ch->esd->decoderConfig->streamType==5) ch->buffer_min=400;
 
223
                                else ch->buffer_min=0;
 
224
 
 
225
                                if (read->needs_connection && (ch->esd->decoderConfig->streamType==GF_STREAM_SCENE)) {
 
226
                                        gf_list_add(read->channels, ch);
 
227
                                        read->needs_connection = 0;
 
228
                                        gf_term_on_connect(read->service, NULL, GF_OK);
 
229
                                } else if (read->needs_connection) {
 
230
                                        gf_odf_desc_del((GF_Descriptor *) ch->esd);
 
231
                                        free(ch);
 
232
                                        ch = NULL;
 
233
                                } else {
 
234
                                        GF_ObjectDescriptor *od;
 
235
                                        gf_list_add(read->channels, ch);
 
236
 
 
237
                                        od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);
 
238
                                        gf_list_add(od->ESDescriptors, ch->esd);
 
239
                                        ch->esd = NULL;
 
240
                                        od->objectDescriptorID = ch->stream_id;
 
241
                                        gf_term_add_media(read->service, (GF_Descriptor*)od, 0);
 
242
 
 
243
                                }
 
244
                        }
 
245
                        break;
 
246
                case 4:
 
247
                        if (ch) {
 
248
                                bs_pos = (u32) gf_bs_get_position(bs);
 
249
                                memset(&sl_hdr, 0, sizeof(GF_SLHeader));
 
250
                                sl_hdr.accessUnitLength = au_size;
 
251
                                sl_hdr.AU_sequenceNumber = au_sn;
 
252
                                sl_hdr.compositionTimeStampFlag = 1;
 
253
                                sl_hdr.compositionTimeStamp = cts;
 
254
                                sl_hdr.randomAccessPointFlag = is_rap;
 
255
                                if (read->start_range && (read->start_range*ch->ts_res>cts*1000)) {
 
256
                                        sl_hdr.compositionTimeStamp = read->start_range*ch->ts_res/1000;
 
257
                                }
 
258
                                gf_term_on_sl_packet(read->service, ch->ch, read->saf_data+bs_pos, au_size, &sl_hdr, GF_OK);
 
259
                        }
 
260
                        gf_bs_skip_bytes(bs, au_size);
 
261
                        break;
 
262
                case 3:
 
263
                        if (ch) gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS);
 
264
                        break;
 
265
                case 5:
 
266
                        go = 0;
 
267
                        read->run_state = 0;
 
268
                        i=0;
 
269
                        while ((ch=gf_list_enum(read->channels, &i))) {
 
270
                                gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS);
 
271
                        }
 
272
                        break;
 
273
                }
 
274
        }
 
275
 
 
276
        gf_bs_del(bs);
 
277
        if (bs_pos) {
 
278
                u32 remain = read->saf_size - bs_pos;
 
279
                if (remain) memmove(read->saf_data, read->saf_data+bs_pos, sizeof(char)*remain);
 
280
                read->saf_size = remain;
 
281
        }
 
282
        SAF_Regulate(read);
 
283
}
 
284
 
 
285
 
 
286
u32 SAF_Run(void *_p)
 
287
{
 
288
        char data[1024];
 
289
        u32 size;
 
290
        SAFIn *read = _p;
 
291
 
 
292
        fseek(read->stream, 0, SEEK_SET);
 
293
        read->saf_size=0;
 
294
        read->run_state = 1;
 
295
        while (read->run_state && !feof(read->stream) ) {
 
296
                size = fread(data, 1, 1024, read->stream);
 
297
                if (!size) break;
 
298
                SAF_OnData(read, data, size, 0, GF_OK);
 
299
        }
 
300
        read->run_state = 2;
 
301
        return 0;
 
302
}
 
303
 
 
304
static void SAF_DownloadFile(GF_InputService *plug, char *url)
 
305
{
 
306
        SAFIn *read = (SAFIn*) plug->priv;
 
307
 
 
308
        read->dnload = gf_term_download_new(read->service, url, 0, SAF_OnData, read);
 
309
        if (!read->dnload) {
 
310
                read->needs_connection = 0;
 
311
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
 
312
        }
 
313
        /*service confirm is done once fetched*/
 
314
}
 
315
 
 
316
typedef struct
 
317
{
 
318
        u32 stream_id;
 
319
        u32 ts_res;
 
320
} StreamInfo;
 
321
 
 
322
static void SAF_CheckFile(SAFIn *read)
 
323
{
 
324
        u32 nb_streams, i, cts, au_size, au_type, stream_id, ts_res;
 
325
        GF_BitStream *bs;
 
326
        StreamInfo si[1024];
 
327
        fseek(read->stream, 0, SEEK_SET);
 
328
        bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ);
 
329
 
 
330
        nb_streams=0;
 
331
        while (gf_bs_available(bs)) {
 
332
                gf_bs_read_u16(bs);
 
333
                gf_bs_read_int(bs, 2);
 
334
                cts = gf_bs_read_int(bs, 30);
 
335
                au_size = gf_bs_read_int(bs, 16);
 
336
                au_type = gf_bs_read_int(bs, 4);
 
337
                stream_id = gf_bs_read_int(bs, 12);
 
338
                au_size-=2;
 
339
                ts_res = 0;
 
340
                for (i=0; i<nb_streams; i++) { if (si[i].stream_id==stream_id) ts_res = si[i].ts_res; }
 
341
                if (!ts_res) {
 
342
                        if ((au_type==1) || (au_type==2) || (au_type==7)) {
 
343
                                gf_bs_read_u16(bs);
 
344
                                ts_res = gf_bs_read_u24(bs);
 
345
                                au_size -= 5;
 
346
                                si[nb_streams].stream_id = stream_id;
 
347
                                si[nb_streams].ts_res = ts_res;
 
348
                                nb_streams++;
 
349
                        }
 
350
                }
 
351
                if (ts_res && (au_type==4)) {
 
352
                        Double ts = cts;
 
353
                        ts /= ts_res;
 
354
                        if (ts>read->duration) read->duration = ts;
 
355
                }
 
356
                gf_bs_skip_bytes(bs, au_size);
 
357
        }
 
358
        gf_bs_del(bs);
 
359
        fseek(read->stream, 0, SEEK_SET);
 
360
}
 
361
 
 
362
static GF_Err SAF_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
 
363
{
 
364
        char szURL[2048];
 
365
        char *ext;
 
366
        SAFIn *read = plug->priv;
 
367
        read->service = serv;
 
368
 
 
369
        if (read->dnload) gf_term_download_del(read->dnload);
 
370
        read->dnload = NULL;
 
371
 
 
372
        strcpy(szURL, url);
 
373
        ext = strrchr(szURL, '#');
 
374
        if (ext) ext[0] = 0;
 
375
 
 
376
        read->needs_connection = 1;
 
377
        read->duration = 0;
 
378
 
 
379
        read->saf_type = SAF_FILE_LOCAL;
 
380
        /*remote fetch*/
 
381
        if (strnicmp(url, "file://", 7) && strstr(url, "://")) {
 
382
                read->saf_type = SAF_FILE_REMOTE;
 
383
                SAF_DownloadFile(plug, (char *) szURL);
 
384
                return GF_OK;
 
385
        }
 
386
 
 
387
        read->stream = fopen(szURL, "rb");
 
388
        if (!read->stream) {
 
389
                gf_term_on_connect(serv, NULL, GF_URL_ERROR);
 
390
                return GF_OK;
 
391
        }
 
392
        SAF_CheckFile(read);
 
393
        read->th = gf_th_new();
 
394
        /*start playing for tune-in*/
 
395
        gf_th_run(read->th, SAF_Run, read);
 
396
        return GF_OK;
 
397
}
 
398
 
 
399
static GF_Err SAF_CloseService(GF_InputService *plug)
 
400
{
 
401
        SAFIn *read = plug->priv;
 
402
 
 
403
        if (read->th) {
 
404
                if (read->run_state == 1) {
 
405
                        read->run_state=0;
 
406
                        while (read->run_state!=2) gf_sleep(0);
 
407
                }
 
408
                gf_th_del(read->th);
 
409
                read->th = NULL;
 
410
        }
 
411
 
 
412
        if (read->stream) fclose(read->stream);
 
413
        read->stream = NULL;
 
414
        if (read->dnload) gf_term_download_del(read->dnload);
 
415
        read->dnload = NULL;
 
416
        gf_term_on_disconnect(read->service, NULL, GF_OK);
 
417
        return GF_OK;
 
418
}
 
419
 
 
420
static GF_Descriptor *SAF_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
 
421
{
 
422
        u32 i=0;
 
423
        SAFChannel *root;
 
424
        SAFIn *read = plug->priv;
 
425
        GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
 
426
 
 
427
        od->objectDescriptorID = 1;
 
428
 
 
429
        while ( (root=gf_list_enum(read->channels, &i))) {
 
430
                if (root->esd && (root->esd->decoderConfig->streamType==GF_STREAM_SCENE)) break;
 
431
        }
 
432
        if (!root) return NULL;
 
433
 
 
434
        /*inline scene*/
 
435
        gf_list_add(od->ESDescriptors, root->esd);
 
436
        root->esd = NULL;
 
437
        return (GF_Descriptor *) od;
 
438
}
 
439
 
 
440
static GF_Err SAF_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
 
441
{
 
442
        u32 ES_ID;
 
443
        SAFChannel *ch;
 
444
        GF_Err e;
 
445
        SAFIn *read = plug->priv;
 
446
 
 
447
 
 
448
        ch = saf_get_channel(read, 0, channel);
 
449
        if (ch) e = GF_SERVICE_ERROR;
 
450
 
 
451
        e = GF_STREAM_NOT_FOUND;
 
452
        if (strstr(url, "ES_ID")) {
 
453
                sscanf(url, "ES_ID=%d", &ES_ID);
 
454
                ch = saf_get_channel(read, ES_ID, NULL);
 
455
                if (ch && !ch->ch) {
 
456
                        ch->ch = channel;
 
457
                        e = GF_OK;
 
458
                }
 
459
        }
 
460
 
 
461
        gf_term_on_connect(read->service, channel, e);
 
462
        return e;
 
463
}
 
464
 
 
465
static GF_Err SAF_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
 
466
{
 
467
        SAFChannel *ch;
 
468
        SAFIn *read = plug->priv;
 
469
 
 
470
        GF_Err e = GF_STREAM_NOT_FOUND;
 
471
        ch = saf_get_channel(read, 0, channel);
 
472
        if (ch) {
 
473
                gf_list_del_item(read->channels, ch);
 
474
                if (ch->esd) gf_odf_desc_del((GF_Descriptor*)ch->esd);
 
475
                free(ch);
 
476
                e = GF_OK;
 
477
        }
 
478
        gf_term_on_disconnect(read->service, channel, e);
 
479
        return GF_OK;
 
480
}
 
481
 
 
482
static GF_Err SAF_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
 
483
{
 
484
        SAFIn *read = plug->priv;
 
485
 
 
486
        if (!com->base.on_channel) return GF_NOT_SUPPORTED;
 
487
        switch (com->command_type) {
 
488
        case GF_NET_CHAN_SET_PULL:
 
489
                return GF_NOT_SUPPORTED;
 
490
        case GF_NET_CHAN_INTERACTIVE:
 
491
                return GF_OK;
 
492
        case GF_NET_CHAN_BUFFER:
 
493
                return GF_OK;
 
494
        case GF_NET_CHAN_DURATION:
 
495
                com->duration.duration = read->duration;
 
496
                return GF_OK;
 
497
        case GF_NET_CHAN_PLAY:
 
498
                if (!read->nb_playing) {
 
499
                        read->start_range = (u32) (com->play.start_range*1000);
 
500
                        read->end_range = (u32) (com->play.end_range*1000);
 
501
                        /*start demuxer*/
 
502
                        if ((read->saf_type == SAF_FILE_LOCAL) && (read->run_state!=1)) {
 
503
                                gf_th_run(read->th, SAF_Run, read);
 
504
                        }
 
505
                }
 
506
                read->nb_playing++;
 
507
                return GF_OK;
 
508
        case GF_NET_CHAN_STOP:
 
509
                assert(read->nb_playing);
 
510
                read->nb_playing--;
 
511
                /*stop demuxer*/
 
512
                if (!read->nb_playing && (read->run_state==1)) {
 
513
                        read->run_state=0;
 
514
                        while (read->run_state!=2) gf_sleep(2);
 
515
                }
 
516
                return GF_OK;
 
517
        default:
 
518
                return GF_OK;
 
519
        }
 
520
}
 
521
 
 
522
 
 
523
GF_InputService *NewSAFReader()
 
524
{
 
525
        SAFIn *reader;
 
526
        GF_InputService *plug = malloc(sizeof(GF_InputService));
 
527
        memset(plug, 0, sizeof(GF_InputService));
 
528
        GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC SAF Reader", "gpac distribution")
 
529
 
 
530
        plug->CanHandleURL = SAF_CanHandleURL;
 
531
        plug->ConnectService = SAF_ConnectService;
 
532
        plug->CloseService = SAF_CloseService;
 
533
        plug->GetServiceDescriptor = SAF_GetServiceDesc;
 
534
        plug->ConnectChannel = SAF_ConnectChannel;
 
535
        plug->DisconnectChannel = SAF_DisconnectChannel;
 
536
        plug->ServiceCommand = SAF_ServiceCommand;
 
537
 
 
538
        reader = malloc(sizeof(SAFIn));
 
539
        memset(reader, 0, sizeof(SAFIn));
 
540
        reader->channels = gf_list_new();
 
541
        plug->priv = reader;
 
542
        return plug;
 
543
}
 
544
 
 
545
void DeleteSAFReader(void *ifce)
 
546
{
 
547
        GF_InputService *plug = (GF_InputService *) ifce;
 
548
        SAFIn *read = plug->priv;
 
549
 
 
550
        while (gf_list_count(read->channels)) {
 
551
                SAFChannel *ch=gf_list_last(read->channels);
 
552
                gf_list_rem_last(read->channels);
 
553
                if (ch->esd) gf_odf_desc_del((GF_Descriptor *) ch->esd);
 
554
                free(ch);
 
555
        }
 
556
        gf_list_del(read->channels);
 
557
        if (read->saf_data) free(read->saf_data);
 
558
        free(read);
 
559
        free(plug);
 
560
}
 
561
 
 
562
 
 
563
Bool QueryInterface(u32 InterfaceType)
 
564
{
 
565
        switch (InterfaceType) {
 
566
        case GF_NET_CLIENT_INTERFACE: return 1;
 
567
        default: return 0;
 
568
        }
 
569
}
 
570
 
 
571
GF_BaseInterface *LoadInterface(u32 InterfaceType)
 
572
{
 
573
        switch (InterfaceType) {
 
574
        case GF_NET_CLIENT_INTERFACE: return (GF_BaseInterface *) NewSAFReader();
 
575
        default: return NULL;
 
576
        }
 
577
}
 
578
 
 
579
void ShutdownInterface(GF_BaseInterface *ifce)
 
580
{
 
581
        switch (ifce->InterfaceType) {
 
582
        case GF_NET_CLIENT_INTERFACE:  DeleteSAFReader(ifce); break;
 
583
        }
 
584
}