Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2005-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / LASeR codec sub-project
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/internal/media_dev.h>
27 : #include <gpac/bitstream.h>
28 : #include <gpac/thread.h>
29 : #include <gpac/list.h>
30 :
31 : enum
32 : {
33 : SAF_STREAM_HEADER = 1,
34 : SAF_STREAM_HEADER_PERMANENT = 2,
35 : SAF_END_OF_STREAM = 3,
36 : SAF_ACCESS_UNIT = 4,
37 : SAF_END_OF_SESSION = 5,
38 : SAF_CACHE_UNIT = 6,
39 : SAF_REMOTE_STREAM_HEADER = 7,
40 : };
41 :
42 :
43 : typedef struct
44 : {
45 : char *data;
46 : u32 data_size;
47 : Bool is_rap;
48 : u32 ts;
49 : } GF_SAFSample;
50 :
51 : typedef struct
52 : {
53 : u32 stream_id;
54 : u32 ts_resolution;
55 : u32 buffersize_db;
56 : u8 stream_type, object_type;
57 : char *mime_type;
58 : char *remote_url;
59 :
60 : char *dsi;
61 : u32 dsi_len;
62 :
63 : GF_List *aus;
64 : /*0: not declared yet; 1: declared; (1<<1) : done but end of stream not sent yet*/
65 : u32 state;
66 : u32 last_au_sn, last_au_ts;
67 : } GF_SAFStream;
68 :
69 : struct __saf_muxer
70 : {
71 : GF_List *streams;
72 : /*0: nothing to do, 1: should regenerate, (1<<1): end of session has been sent*/
73 : u32 state;
74 : GF_Mutex *mx;
75 : };
76 :
77 1 : GF_SAFMuxer *gf_saf_mux_new()
78 : {
79 : GF_SAFMuxer *mux;
80 1 : GF_SAFEALLOC(mux, GF_SAFMuxer);
81 1 : if (!mux) return NULL;
82 1 : mux->mx = gf_mx_new("SAF");
83 1 : mux->streams = gf_list_new();
84 1 : return mux;
85 : }
86 :
87 1 : static void saf_stream_del(GF_SAFStream *str)
88 : {
89 1 : if (str->mime_type) gf_free(str->mime_type);
90 1 : if (str->remote_url) gf_free(str->remote_url);
91 1 : if (str->dsi) gf_free(str->dsi);
92 :
93 1 : while (gf_list_count(str->aus)) {
94 0 : GF_SAFSample *au = (GF_SAFSample *)gf_list_last(str->aus);
95 0 : gf_list_rem_last(str->aus);
96 0 : if (au->data) gf_free(au->data);
97 0 : gf_free(au);
98 : }
99 1 : gf_list_del(str->aus);
100 1 : gf_free(str);
101 1 : }
102 :
103 1 : void gf_saf_mux_del(GF_SAFMuxer *mux)
104 : {
105 3 : while (gf_list_count(mux->streams)) {
106 1 : GF_SAFStream *str = (GF_SAFStream *)gf_list_last(mux->streams);
107 1 : gf_list_rem_last(mux->streams);
108 1 : saf_stream_del(str);
109 : }
110 1 : gf_list_del(mux->streams);
111 1 : gf_mx_del(mux->mx);
112 1 : gf_free(mux);
113 1 : }
114 :
115 : static GFINLINE GF_SAFStream *saf_get_stream(GF_SAFMuxer *mux, u32 stream_id)
116 : {
117 : GF_SAFStream *str;
118 4 : u32 i=0;
119 4 : while ( (str = (GF_SAFStream *)gf_list_enum(mux->streams, &i)) ) {
120 3 : if (str->stream_id==stream_id) return str;
121 : }
122 : return NULL;
123 : }
124 :
125 1 : GF_Err gf_saf_mux_stream_add(GF_SAFMuxer *mux, u32 stream_id, u32 ts_res, u32 buffersize_db, u8 stream_type, u8 object_type, char *mime_type, char *dsi, u32 dsi_len, char *remote_url)
126 : {
127 : GF_SAFStream *str = saf_get_stream(mux, stream_id);
128 1 : if (str) return GF_BAD_PARAM;
129 :
130 1 : if (mux->state == 2) return GF_BAD_PARAM;
131 :
132 1 : gf_mx_p(mux->mx);
133 :
134 1 : GF_SAFEALLOC(str, GF_SAFStream);
135 1 : if (!str) return GF_OUT_OF_MEM;
136 1 : str->stream_id = stream_id;
137 1 : str->ts_resolution = ts_res;
138 1 : str->buffersize_db = buffersize_db;
139 1 : str->stream_type = stream_type;
140 1 : str->object_type = object_type;
141 1 : if (mime_type) {
142 0 : str->mime_type = gf_strdup(mime_type);
143 0 : str->stream_type = str->object_type = 0xFF;
144 : }
145 1 : str->dsi_len = dsi_len;
146 1 : if (dsi_len) {
147 1 : str->dsi = (char *) gf_malloc(sizeof(char)*dsi_len);
148 : memcpy(str->dsi, dsi, sizeof(char)*dsi_len);
149 : }
150 1 : if (remote_url) str->remote_url = gf_strdup(remote_url);
151 1 : str->aus = gf_list_new();
152 1 : mux->state = 0;
153 1 : gf_list_add(mux->streams, str);
154 1 : gf_mx_v(mux->mx);
155 1 : return GF_OK;
156 : }
157 :
158 : #if 0 //unused
159 : /*!
160 : Removes a stream from the SAF multiplex
161 : \param mux the SAF multiplexer object
162 : \param stream_id ID of the SAF stream to remove
163 : \return error if any
164 : */
165 : GF_Err gf_saf_mux_stream_rem(GF_SAFMuxer *mux, u32 stream_id)
166 : {
167 : GF_SAFStream *str = saf_get_stream(mux, stream_id);
168 : if (!str) return GF_BAD_PARAM;
169 : if (mux->state == 2) return GF_BAD_PARAM;
170 :
171 : gf_mx_p(mux->mx);
172 : str->state |= 2;
173 : mux->state = 1;
174 : gf_mx_v(mux->mx);
175 : return GF_OK;
176 : }
177 : #endif
178 :
179 :
180 3 : GF_Err gf_saf_mux_add_au(GF_SAFMuxer *mux, u32 stream_id, u32 CTS, char *data, u32 data_len, Bool is_rap)
181 : {
182 : GF_SAFSample *au;
183 : GF_SAFStream *str = saf_get_stream(mux, stream_id);
184 3 : if (!str) return GF_BAD_PARAM;
185 3 : if (mux->state == 2) return GF_BAD_PARAM;
186 :
187 3 : gf_mx_p(mux->mx);
188 :
189 3 : GF_SAFEALLOC(au, GF_SAFSample);
190 3 : if (!au) return GF_OUT_OF_MEM;
191 3 : au->data = data;
192 3 : au->data_size = data_len;
193 3 : au->is_rap = is_rap;
194 3 : au->ts = CTS;
195 3 : mux->state = 1;
196 :
197 3 : gf_list_add(str->aus, au);
198 3 : gf_mx_v(mux->mx);
199 3 : return GF_OK;
200 : }
201 :
202 :
203 7 : GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, u8 **out_data, u32 *out_size)
204 : {
205 : u32 i, count, dlen;
206 : u8 *data;
207 : GF_SAFStream *str;
208 : GF_SAFSample*au;
209 : GF_BitStream *bs, *payload;
210 :
211 7 : *out_data = NULL;
212 7 : *out_size = 0;
213 :
214 7 : gf_mx_p(mux->mx);
215 7 : if (!force_end_of_session && (mux->state!=1)) {
216 3 : gf_mx_v(mux->mx);
217 3 : return GF_OK;
218 : }
219 :
220 4 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
221 :
222 4 : count = gf_list_count(mux->streams);
223 :
224 : /*1: write all stream headers*/
225 8 : for (i=0; i<count; i++) {
226 4 : str = (GF_SAFStream *)gf_list_get(mux->streams, i);
227 4 : if (str->state & 1) continue;
228 :
229 1 : au = (GF_SAFSample *)gf_list_get(str->aus, 0);
230 :
231 : /*write stream declaration*/
232 1 : payload = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
233 1 : gf_bs_write_int(payload, str->remote_url ? SAF_REMOTE_STREAM_HEADER : SAF_STREAM_HEADER, 4);
234 1 : gf_bs_write_int(payload, str->stream_id, 12);
235 :
236 1 : gf_bs_write_u8(payload, str->object_type);
237 1 : gf_bs_write_u8(payload, str->stream_type);
238 1 : gf_bs_write_int(payload, str->ts_resolution, 24);
239 1 : gf_bs_write_u16(payload, str->buffersize_db);
240 1 : if (str->mime_type) {
241 0 : u32 len = (u32) strlen(str->mime_type);
242 0 : gf_bs_write_u16(payload, len);
243 0 : gf_bs_write_data(payload, str->mime_type, len);
244 : }
245 1 : if (str->remote_url) {
246 0 : u32 len = (u32) strlen(str->remote_url);
247 0 : gf_bs_write_u16(payload, len);
248 0 : gf_bs_write_data(payload, str->remote_url, len);
249 : }
250 1 : if (str->dsi) {
251 1 : gf_bs_write_data(payload, str->dsi, str->dsi_len);
252 : }
253 :
254 1 : gf_bs_get_content(payload, &data, &dlen);
255 1 : gf_bs_del(payload);
256 :
257 : /*write SAF packet header*/
258 1 : gf_bs_write_int(bs, 1, 1);
259 1 : gf_bs_write_int(bs, 0, 15);
260 1 : gf_bs_write_int(bs, 0, 1);
261 1 : gf_bs_write_int(bs, 1, 1);
262 1 : gf_bs_write_int(bs, au ? au->ts : 0, 30);
263 1 : gf_bs_write_int(bs, dlen, 16);
264 1 : gf_bs_write_data(bs, data, dlen);
265 1 : gf_free(data);
266 :
267 : /*mark as signaled*/
268 1 : str->state |= 1;
269 : }
270 :
271 : /*write all pending AUs*/
272 3 : while (1) {
273 : GF_SAFStream *src = NULL;
274 : u32 mux_time = time_ms;
275 :
276 14 : for (i=0; i<count; i++) {
277 7 : str = (GF_SAFStream*)gf_list_get(mux->streams, i);
278 7 : au = (GF_SAFSample*)gf_list_get(str->aus, 0);
279 7 : if (au && (au->ts*1000 < mux_time*str->ts_resolution)) {
280 3 : mux_time = 1000*au->ts/str->ts_resolution;
281 : src = str;
282 : }
283 : }
284 :
285 7 : if (!src) break;
286 :
287 3 : au = (GF_SAFSample*)gf_list_get(src->aus, 0);
288 3 : gf_list_rem(src->aus, 0);
289 :
290 : /*write stream declaration*/
291 3 : gf_bs_write_int(bs, au->is_rap ? 1 : 0, 1);
292 3 : gf_bs_write_int(bs, src->last_au_sn, 15);
293 3 : gf_bs_write_int(bs, 0, 1);
294 3 : gf_bs_write_int(bs, 1, 1);
295 3 : gf_bs_write_int(bs, au->ts, 30);
296 3 : gf_bs_write_u16(bs, 2+au->data_size);
297 3 : gf_bs_write_int(bs, SAF_ACCESS_UNIT, 4);
298 3 : gf_bs_write_int(bs, src->stream_id, 12);
299 3 : gf_bs_write_data(bs, au->data, au->data_size);
300 :
301 3 : src->last_au_sn ++;
302 3 : src->last_au_ts = au->ts;
303 3 : gf_free(au->data);
304 3 : gf_free(au);
305 : }
306 :
307 : /*3: write all end of stream*/
308 4 : for (i=0; i<count; i++) {
309 4 : str = (GF_SAFStream*)gf_list_get(mux->streams, i);
310 : /*mark as signaled*/
311 4 : if (!(str->state & 2)) continue;
312 0 : if (gf_list_count(str->aus)) continue;
313 :
314 : /*write stream declaration*/
315 0 : gf_bs_write_int(bs, 1, 1);
316 0 : gf_bs_write_int(bs, str->last_au_sn, 15);
317 0 : gf_bs_write_int(bs, 0, 1);
318 0 : gf_bs_write_int(bs, 1, 1);
319 0 : gf_bs_write_int(bs, str->last_au_ts, 30);
320 0 : gf_bs_write_int(bs, 2, 16);
321 0 : gf_bs_write_int(bs, SAF_END_OF_STREAM, 4);
322 0 : gf_bs_write_int(bs, str->stream_id, 12);
323 :
324 : /*remove stream*/
325 0 : gf_list_rem(mux->streams, i);
326 0 : i--;
327 0 : count--;
328 0 : saf_stream_del(str);
329 : }
330 4 : mux->state = 0;
331 4 : if (force_end_of_session) {
332 1 : gf_bs_write_int(bs, 1, 1);
333 1 : gf_bs_write_int(bs, 0, 15);
334 1 : gf_bs_write_int(bs, 0, 1);
335 1 : gf_bs_write_int(bs, 1, 1);
336 1 : gf_bs_write_int(bs, 0, 30);
337 1 : gf_bs_write_int(bs, 2, 16);
338 1 : gf_bs_write_int(bs, SAF_END_OF_SESSION, 4);
339 1 : gf_bs_write_int(bs, 0, 12);
340 1 : mux->state = 2;
341 : }
342 4 : gf_bs_get_content(bs, out_data, out_size);
343 4 : gf_bs_del(bs);
344 4 : gf_mx_v(mux->mx);
345 4 : return GF_OK;
346 : }
|