2
* GPAC - Multimedia Framework C SDK
4
* Authors: Jean le Feuvre
5
* Copyright (c) 2005-200X ENST
8
* This file is part of GPAC / SAF reader module
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)
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.
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.
26
#include <gpac/modules/service.h>
27
#include <gpac/modules/codec.h>
28
#include <gpac/constants.h>
29
#include <gpac/thread.h>
34
u32 au_sn, stream_id, ts_res, buffer_min;
47
GF_ClientService *service;
49
Bool needs_connection;
54
GF_DownloadSession * dnload;
56
/*SAF buffer for both lcoal, remote and live streams*/
58
u32 saf_size, alloc_size;
60
/*local file playing*/
64
u32 start_range, end_range;
69
static GFINLINE SAFChannel *saf_get_channel(SAFIn *saf, u32 stream_id, LPNETCHANNEL a_ch)
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;
80
static Bool SAF_CanHandleURL(GF_InputService *plug, const char *url)
83
sExt = strrchr(url, '.');
85
if (gf_term_check_extension(plug, "application/x-saf", "saf lsr", "SAF Rich Media", sExt)) return 1;
89
static void SAF_Regulate(SAFIn *read)
91
GF_NetworkCommand com;
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;
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);
106
if (min_occ == (u32) -1) break;
107
//fprintf(stdout, "Regulating SAF demux - sleeping for %d ms\n", min_occ);
112
static void SAF_OnData(void *cbk, char *data, u32 size, u32 status, GF_Err e)
116
u32 cts, au_sn, au_size, bs_pos, type, i, stream_id;
120
SAFIn *read = (SAFIn *) cbk;
123
if ((e == GF_EOS) && read->stream) {
124
if (read->saf_type==SAF_FILE_REMOTE) read->saf_type = SAF_FILE_LOCAL;
127
/*handle service message*/
129
gf_term_download_update_stats(read->dnload);
130
if (read->needs_connection) {
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;
139
if (read->needs_connection) {
140
read->needs_connection = 0;
141
gf_term_on_connect(read->service, NULL, e);
145
if (!read->run_state) return;
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;
151
memcpy(read->saf_data + read->saf_size, data, sizeof(char)*size);
152
read->saf_size+=size;
154
/*first AU not complete yet*/
155
if (read->saf_size<10) return;
157
bs = gf_bs_new(read->saf_data, read->saf_size, GF_BITSTREAM_READ);
162
u32 avail = (u32) gf_bs_available(bs);
163
bs_pos = (u32) gf_bs_get_position(bs);
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);
174
if (au_size > avail) break;
179
type = gf_bs_read_int(bs, 4);
180
stream_id = gf_bs_read_int(bs, 12);
183
ch = saf_get_channel(read, stream_id, NULL);
189
gf_bs_skip_bytes(bs, au_size);
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);
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;
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;
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);
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;
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);
234
GF_ObjectDescriptor *od;
235
gf_list_add(read->channels, ch);
237
od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);
238
gf_list_add(od->ESDescriptors, ch->esd);
240
od->objectDescriptorID = ch->stream_id;
241
gf_term_add_media(read->service, (GF_Descriptor*)od, 0);
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;
258
gf_term_on_sl_packet(read->service, ch->ch, read->saf_data+bs_pos, au_size, &sl_hdr, GF_OK);
260
gf_bs_skip_bytes(bs, au_size);
263
if (ch) gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS);
269
while ((ch=gf_list_enum(read->channels, &i))) {
270
gf_term_on_sl_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS);
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;
286
u32 SAF_Run(void *_p)
292
fseek(read->stream, 0, SEEK_SET);
295
while (read->run_state && !feof(read->stream) ) {
296
size = fread(data, 1, 1024, read->stream);
298
SAF_OnData(read, data, size, 0, GF_OK);
304
static void SAF_DownloadFile(GF_InputService *plug, char *url)
306
SAFIn *read = (SAFIn*) plug->priv;
308
read->dnload = gf_term_download_new(read->service, url, 0, SAF_OnData, read);
310
read->needs_connection = 0;
311
gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
313
/*service confirm is done once fetched*/
322
static void SAF_CheckFile(SAFIn *read)
324
u32 nb_streams, i, cts, au_size, au_type, stream_id, ts_res;
327
fseek(read->stream, 0, SEEK_SET);
328
bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ);
331
while (gf_bs_available(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);
340
for (i=0; i<nb_streams; i++) { if (si[i].stream_id==stream_id) ts_res = si[i].ts_res; }
342
if ((au_type==1) || (au_type==2) || (au_type==7)) {
344
ts_res = gf_bs_read_u24(bs);
346
si[nb_streams].stream_id = stream_id;
347
si[nb_streams].ts_res = ts_res;
351
if (ts_res && (au_type==4)) {
354
if (ts>read->duration) read->duration = ts;
356
gf_bs_skip_bytes(bs, au_size);
359
fseek(read->stream, 0, SEEK_SET);
362
static GF_Err SAF_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
366
SAFIn *read = plug->priv;
367
read->service = serv;
369
if (read->dnload) gf_term_download_del(read->dnload);
373
ext = strrchr(szURL, '#');
376
read->needs_connection = 1;
379
read->saf_type = SAF_FILE_LOCAL;
381
if (strnicmp(url, "file://", 7) && strstr(url, "://")) {
382
read->saf_type = SAF_FILE_REMOTE;
383
SAF_DownloadFile(plug, (char *) szURL);
387
read->stream = fopen(szURL, "rb");
389
gf_term_on_connect(serv, NULL, GF_URL_ERROR);
393
read->th = gf_th_new();
394
/*start playing for tune-in*/
395
gf_th_run(read->th, SAF_Run, read);
399
static GF_Err SAF_CloseService(GF_InputService *plug)
401
SAFIn *read = plug->priv;
404
if (read->run_state == 1) {
406
while (read->run_state!=2) gf_sleep(0);
412
if (read->stream) fclose(read->stream);
414
if (read->dnload) gf_term_download_del(read->dnload);
416
gf_term_on_disconnect(read->service, NULL, GF_OK);
420
static GF_Descriptor *SAF_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
424
SAFIn *read = plug->priv;
425
GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
427
od->objectDescriptorID = 1;
429
while ( (root=gf_list_enum(read->channels, &i))) {
430
if (root->esd && (root->esd->decoderConfig->streamType==GF_STREAM_SCENE)) break;
432
if (!root) return NULL;
435
gf_list_add(od->ESDescriptors, root->esd);
437
return (GF_Descriptor *) od;
440
static GF_Err SAF_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
445
SAFIn *read = plug->priv;
448
ch = saf_get_channel(read, 0, channel);
449
if (ch) e = GF_SERVICE_ERROR;
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);
461
gf_term_on_connect(read->service, channel, e);
465
static GF_Err SAF_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
468
SAFIn *read = plug->priv;
470
GF_Err e = GF_STREAM_NOT_FOUND;
471
ch = saf_get_channel(read, 0, channel);
473
gf_list_del_item(read->channels, ch);
474
if (ch->esd) gf_odf_desc_del((GF_Descriptor*)ch->esd);
478
gf_term_on_disconnect(read->service, channel, e);
482
static GF_Err SAF_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
484
SAFIn *read = plug->priv;
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:
492
case GF_NET_CHAN_BUFFER:
494
case GF_NET_CHAN_DURATION:
495
com->duration.duration = read->duration;
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);
502
if ((read->saf_type == SAF_FILE_LOCAL) && (read->run_state!=1)) {
503
gf_th_run(read->th, SAF_Run, read);
508
case GF_NET_CHAN_STOP:
509
assert(read->nb_playing);
512
if (!read->nb_playing && (read->run_state==1)) {
514
while (read->run_state!=2) gf_sleep(2);
523
GF_InputService *NewSAFReader()
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")
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;
538
reader = malloc(sizeof(SAFIn));
539
memset(reader, 0, sizeof(SAFIn));
540
reader->channels = gf_list_new();
545
void DeleteSAFReader(void *ifce)
547
GF_InputService *plug = (GF_InputService *) ifce;
548
SAFIn *read = plug->priv;
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);
556
gf_list_del(read->channels);
557
if (read->saf_data) free(read->saf_data);
563
Bool QueryInterface(u32 InterfaceType)
565
switch (InterfaceType) {
566
case GF_NET_CLIENT_INTERFACE: return 1;
571
GF_BaseInterface *LoadInterface(u32 InterfaceType)
573
switch (InterfaceType) {
574
case GF_NET_CLIENT_INTERFACE: return (GF_BaseInterface *) NewSAFReader();
575
default: return NULL;
579
void ShutdownInterface(GF_BaseInterface *ifce)
581
switch (ifce->InterfaceType) {
582
case GF_NET_CLIENT_INTERFACE: DeleteSAFReader(ifce); break;