1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Cyril Concolato
5  *			Copyright (c) Telecom ParisTech 2013-2019
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / HTML Media Element header
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 
27 #ifndef _GF_HTMLMEDIA_H_
28 #define _GF_HTMLMEDIA_H_
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 
35 /*!
36 \file <gpac/html5_media.h>
37 \brief Scene graph extensions for HTML5 media.
38  */
39 
40 /*!
41 \defgroup html5_grp HTML5
42 \ingroup scene_grp
43 \brief HTML5 extensions of the scene graph.
44 */
45 
46 /*!
47 \addtogroup html5media_grp HTML5 media
48 \ingroup html5_grp
49 \brief Scene graph extensions for HTML5 media.
50 
51 This section documents the scene graph extensions used for HTML5 media (video).
52 
53 @{
54  */
55 
56 #include <gpac/internal/scenegraph_dev.h>
57 
58 /*base SVG type*/
59 #include <gpac/nodes_svg.h>
60 /*dom events*/
61 #include <gpac/events.h>
62 /*dom text event*/
63 #include <gpac/utf.h>
64 
65 #include <gpac/download.h>
66 #include <gpac/network.h>
67 #include <gpac/xml.h>
68 #include <gpac/internal/compositor_dev.h>
69 
70 #ifdef GPAC_ENABLE_HTML5_MEDIA
71 
72 typedef struct
73 {
74 	u32 nb_inst;
75 	/* Basic classes */
76 	JSClassDef  arrayBufferClass;
77 
78 	/*HTML Media classes*/
79 	JSClassDef  htmlVideoElementClass;
80 	JSClassDef  htmlAudioElementClass;
81 	JSClassDef  htmlSourceElementClass;
82 	JSClassDef  htmlTrackElementClass;
83 	JSClassDef  htmlMediaElementClass;
84 	JSClassDef  mediaControllerClass;
85 	JSClassDef  audioTrackListClass;
86 	JSClassDef  audioTrackClass;
87 	JSClassDef  videoTrackListClass;
88 	JSClassDef  videoTrackClass;
89 	JSClassDef  textTrackListClass;
90 	JSClassDef  textTrackClass;
91 	JSClassDef  textTrackCueListClass;
92 	JSClassDef  textTrackCueClass;
93 	JSClassDef  timeRangesClass;
94 	JSClassDef  trackEventClass;
95 	JSClassDef  mediaErrorClass;
96 
97 	/* Media Source Extensions */
98 	JSClassDef  mediaSourceClass;
99 	JSClassDef  sourceBufferClass;
100 	JSClassDef  sourceBufferListClass;
101 	JSClassDef  URLClass;
102 
103 	/* Media Capture */
104 	JSClassDef  mediaStreamClass;
105 	JSClassDef  localMediaStreamClass;
106 	JSClassDef  mediaStreamTrackClass;
107 	JSClassDef  mediaStreamTrackListClass;
108 	JSClassDef  navigatorUserMediaClass;
109 	JSClassDef  navigatorUserMediaErrorClass;
110 } GF_HTML_MediaRuntime;
111 
112 /************************************************************
113  *
114  *  HTML 5 Media Element
115  *  http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#media-element
116  *
117  *************************************************************/
118 
119 typedef enum
120 {
121 	MEDIA_ERR_ABORTED           = 1,
122 	MEDIA_ERR_NETWORK           = 2,
123 	MEDIA_ERR_DECODE            = 3,
124 	MEDIA_ERR_SRC_NOT_SUPPORTED = 4
125 } GF_HTML_MediaErrorCode;
126 
127 typedef enum
128 {
129 	NETWORK_EMPTY               = 0,
130 	NETWORK_IDLE                = 1,
131 	NETWORK_LOADING             = 2,
132 	NETWORK_NO_SOURCE           = 3
133 } GF_HTML_NetworkState;
134 
135 typedef enum
136 {
137 	HAVE_NOTHING                = 0,
138 	HAVE_METADATA               = 1,
139 	HAVE_CURRENT_DATA           = 2,
140 	HAVE_FUTURE_DATA            = 3,
141 	HAVE_ENOUGH_DATA            = 4
142 } GF_HTML_MediaReadyState;
143 
144 typedef struct
145 {
146 	/* JavaScript context associated to this object */
147 	JSContext               *c;
148 	/* JavaScript counterpart */
149 	JSObject                *_this;
150 
151 	GF_HTML_MediaErrorCode   code;
152 } GF_HTML_MediaError;
153 
154 typedef struct _timerange
155 {
156 	/* JavaScript context associated to this object */
157 	JSContext               *c;
158 	/* JavaScript counterpart */
159 	JSObject                *_this;
160 
161 	GF_List                 *times;
162 	u32						timescale;
163 } GF_HTML_MediaTimeRanges;
164 
165 typedef enum {
166 	HTML_MEDIA_TRACK_TYPE_UNKNOWN = 0,
167 	HTML_MEDIA_TRACK_TYPE_AUDIO = 1,
168 	HTML_MEDIA_TRACK_TYPE_VIDEO = 2,
169 	HTML_MEDIA_TRACK_TYPE_TEXT  = 3
170 } GF_HTML_TrackType;
171 
172 #define BASE_HTML_TRACK     \
173     /* JavaScript context associated to this object */\
174     JSContext               *c;\
175     /* JavaScript counterpart */\
176     JSObject                *_this;\
177     /* GPAC-specific properties */\
178     u32                     bin_id;    /* track id */\
179     void *            channel;   /* channel object used by the terminal */\
180     GF_ObjectDescriptor     *od;       /* MPEG-4 Object descriptor for this track */\
181     GF_List                 *buffer;   /* List of MSE Packets */\
182     u32						packet_index;   /* index of MSE Packets*/\
183     GF_Mutex                *buffer_mutex;\
184     Bool                    last_dts_set; \
185     u64						last_dts; /* MSE  last decode timestamp (in timescale units)*/ \
186     u32						last_dur; /* MSE  last frame duration (in timescale units)*/ \
187     Bool                    highest_pts_set; \
188     u64						highest_pts; /* MSE highest presentation timestamp (in timescale units)*/ \
189     Bool                    needs_rap; /* MSE  need random access point flag */ \
190     u32                     timescale; /* used by time stamps in MSE Packets */ \
191     s64                     timestampOffset; /* MSE SourceBuffer value (in timescale units) */ \
192     /* standard HTML properties */ \
193     GF_HTML_TrackType        type;\
194     char                    *id;\
195     char                    *kind;\
196     char                    *label;\
197     char                    *language;\
198     char                    *mime; \
199     Bool                    enabled_or_selected;
200 
201 typedef struct
202 {
203 	BASE_HTML_TRACK
204 } GF_HTML_Track;
205 
206 typedef struct
207 {
208 	BASE_HTML_TRACK
209 	JSFunction				*oncuechange;
210 	char                    *inBandMetadataTrackDispatchType;
211 	//GF_HTMLTextTrackMode    mode;
212 	//GF_HTMLTextTrackCueList cues;
213 	//GF_HTMLTextTrackCueList activeCues;
214 } GF_HTML_TextTrack;
215 
216 #define BASE_HTML_TRACK_LIST     \
217     /* JavaScript context associated to this object */\
218     JSContext               *c;\
219     /* JavaScript counterpart */\
220     JSObject                *_this;\
221     GF_List                 *tracks; \
222 	jsval					onchange; \
223 	jsval					onaddtrack; \
224 	jsval					onremovetrack; \
225     u32                     selected_index;
226 
227 typedef struct
228 {
229 	BASE_HTML_TRACK_LIST
230 } GF_HTML_TrackList;
231 
232 typedef enum
233 {
234 	MEDIA_CONTROLLER_WAITING = 0,
235 	MEDIA_CONTROLLER_PLAYING = 1,
236 	MEDIA_CONTROLLER_ENDED   = 2
237 } GF_HTML_MediaControllerPlaybackState;
238 
239 typedef struct
240 {
241 	/* JavaScript context associated to this object */
242 	JSContext               *c;
243 	/* JavaScript counterpart */
244 	JSObject                *_this;
245 
246 	GF_HTML_MediaTimeRanges  *buffered;
247 	GF_HTML_MediaTimeRanges  *seekable;
248 	GF_HTML_MediaTimeRanges  *played;
249 	Bool                    paused;
250 	GF_HTML_MediaControllerPlaybackState playbackState;
251 	double                  defaultPlaybackRate;
252 
253 	/* list of media elements using this media controller */
254 	GF_List                 *media_elements;
255 } GF_HTML_MediaController;
256 
257 typedef struct
258 {
259 	/* JavaScript context associated to this object */
260 	JSContext               *c;
261 	/* JavaScript counterpart */
262 	JSObject                *_this;
263 
264 	/* The audio or video node */
265 	GF_Node                 *node;
266 
267 	/* error state */
268 	GF_HTML_MediaError       error;
269 
270 	/* src: not stored in this structure,
271 	        using the value stored in the node ( see HTML 5 "must reflect the content of the attribute")*/
272 	/* currentSrc: the actual source used for the video (src attribute on video, audio or source elements) */
273 	char                    *currentSrc;
274 	/* crossOrigin: "must reflect the content of the attribute of the same name", use the node */
275 	/* networkState: retrieved dynamically from GPAC Service */
276 	/* preload: "must reflect the content of the attribute of the same name", use the node */
277 	GF_HTML_MediaTimeRanges  *buffered;
278 	/* ready state */
279 	/* readyState: retrieved from GPAC Media Object dynamically */
280 	Bool                    seeking;
281 
282 	/* playback state */
283 	/* currentTime: retrieved from GPAC Media Object */
284 	/* duration: retrieved from GPAC Media Object */
285 	char                    *startDate;
286 	Bool                    paused;
287 	double                  defaultPlaybackRate;
288 	GF_HTML_MediaTimeRanges  *played;
289 	GF_HTML_MediaTimeRanges  *seekable;
290 	/* ended: retrieved from the state of GPAC Media Object */
291 	/* autoplay: "must reflect the content of the attribute of the same name", use the node */
292 	/* loop: "must reflect the content of the attribute of the same name", use the node */
293 
294 	/* media controller*/
295 	/* mediaGroup: "must reflect the content of the attribute of the same name", use the node */
296 	GF_HTML_MediaController  *controller;
297 
298 	/* controls*/
299 	/* controls: "must reflect the content of the attribute of the same name", use the node */
300 	/* volume: retrieved from GPAC Audio Input in GPAC Media Object */
301 	/* muted: retrieved from GPAC media object */
302 	/* defaultMuted: "must reflect the content of the attribute of with the name" muted */
303 
304 	/* tracks*/
305 	GF_HTML_TrackList        audioTracks;
306 	GF_HTML_TrackList        videoTracks;
307 	GF_HTML_TrackList        textTracks;
308 
309 	GF_DOMEventTarget		 *evt_target;
310 } GF_HTML_MediaElement;
311 
312 typedef struct
313 {
314 	/* JavaScript context used to create the JavaScript object below */
315 	JSContext               *c;
316 
317 	/* JavaScript counterpart for this object*/
318 	JSObject                *_this;
319 
320 	char    *data;
321 	u32     length;
322 	char    *url;
323 	Bool	is_init;
324 	GF_Blob blob;
325 	/* used to do proper garbage collection between JS and Terminal */
326 	u32     reference_count;
327 } GF_HTML_ArrayBuffer;
328 
329 /*
330  * TimeRanges
331  */
332 GF_HTML_MediaTimeRanges *gf_html_timeranges_new(u32 timescale);
333 GF_Err gf_html_timeranges_add_start(GF_HTML_MediaTimeRanges *timeranges, u64 start);
334 GF_Err gf_html_timeranges_add_end(GF_HTML_MediaTimeRanges *timeranges, u64 end);
335 void	gf_html_timeranges_reset(GF_HTML_MediaTimeRanges *range);
336 void	gf_html_timeranges_del(GF_HTML_MediaTimeRanges *range);
337 GF_HTML_MediaTimeRanges *gf_html_timeranges_intersection(GF_HTML_MediaTimeRanges *a, GF_HTML_MediaTimeRanges *b);
338 GF_HTML_MediaTimeRanges *gf_html_timeranges_union(GF_HTML_MediaTimeRanges *a, GF_HTML_MediaTimeRanges *b);
339 
340 /*
341  * HTML5 TrackList
342  */
343 GF_HTML_Track *html_media_add_new_track_to_list(GF_HTML_TrackList *tracklist,
344         GF_HTML_TrackType type, const char *mime, Bool enable_or_selected,
345         const char *id, const char *kind, const char *label, const char *lang);
346 Bool html_media_tracklist_has_track(GF_HTML_TrackList *tracklist, const char *id);
347 GF_HTML_Track *html_media_tracklist_get_track(GF_HTML_TrackList *tracklist, const char *id);
348 void gf_html_tracklist_del(GF_HTML_TrackList *tlist);
349 
350 /*
351  * HTML5 Tracks
352  */
353 GF_HTML_Track *gf_html_media_track_new(GF_HTML_TrackType type, const char *mime, Bool enable_or_selected,
354                                        const char *id, const char *kind, const char *label, const char *lang);
355 void gf_html_track_del(GF_HTML_Track *track);
356 
357 /*
358  * HTML5 Media Element
359  */
360 GF_HTML_MediaElement *gf_html_media_element_new(GF_Node *media_node, GF_HTML_MediaController *mc);
361 void gf_html_media_element_del(GF_HTML_MediaElement *me);
362 
363 void html_media_element_js_init(JSContext *c, JSObject *new_obj, GF_Node *n);
364 
365 /*
366  * HTML5 Media Controller
367  */
368 GF_HTML_MediaController *gf_html_media_controller_new();
369 void gf_html_media_controller_del(GF_HTML_MediaController *mc);
370 
371 /*
372  * HTML5 Array Buffer
373  */
374 GF_HTML_ArrayBuffer *gf_arraybuffer_new(u8 *data, u32 length);
375 JSObject *gf_arraybuffer_js_new(JSContext *c, u8 *data, u32 length, JSObject *parent);
376 void gf_arraybuffer_del(GF_HTML_ArrayBuffer *buffer, Bool del_js);
377 
378 
379 #endif //GPAC_ENABLE_HTML5_MEDIA
380 
381 /*! @} */
382 
383 #ifdef __cplusplus
384 }
385 #endif
386 
387 #endif	// _GF_HTMLMEDIA_H_
388