This source file includes following definitions.
- gf_html_timeranges_new
- gf_html_timeranges_add_time
- gf_html_timeranges_add_start
- gf_html_timeranges_add_end
- gf_html_timeranges_reset
- gf_html_timeranges_del
- gf_html_timeranges_merge
- gf_html_timeranges_union
- gf_html_timeranges_intersection
- html_media_add_new_track_to_list
- html_media_tracklist_has_track
- html_media_tracklist_get_track
- gf_html_tracklist_del
- gf_html_media_track_new
- gf_html_track_del
- gf_html_media_element_new
- gf_html_media_element_del
- gf_html_media_controller_new
- gf_html_mediacontroller_del
#include <gpac/setup.h>
#include <gpac/internal/scenegraph_dev.h>
#ifdef GPAC_HAS_SPIDERMONKEY
#include <gpac/html5_media.h>
#include <gpac/html5_mse.h>
GF_HTML_MediaTimeRanges *gf_html_timeranges_new(u32 timescale)
{
GF_HTML_MediaTimeRanges *ranges;
GF_SAFEALLOC(ranges, GF_HTML_MediaTimeRanges);
if (!ranges) return NULL;
ranges->times = gf_list_new();
ranges->timescale = timescale;
return ranges;
}
static GF_Err gf_html_timeranges_add_time(GF_HTML_MediaTimeRanges *timeranges, u64 time)
{
u64 *t;
if (!timeranges) return GF_BAD_PARAM;
t = (u64 *)gf_malloc(sizeof(u64));
*t = time;
gf_list_add(timeranges->times, t);
return GF_OK;
}
GF_Err gf_html_timeranges_add_start(GF_HTML_MediaTimeRanges *timeranges, u64 start)
{
return gf_html_timeranges_add_time(timeranges, start);
}
GF_Err gf_html_timeranges_add_end(GF_HTML_MediaTimeRanges *timeranges, u64 end)
{
return gf_html_timeranges_add_time(timeranges, end);
}
void gf_html_timeranges_reset(GF_HTML_MediaTimeRanges *ranges)
{
while (gf_list_count(ranges->times))
{
u64 *d = (u64 *)gf_list_get(ranges->times, 0);
gf_free(d);
gf_list_rem(ranges->times, 0);
}
}
void gf_html_timeranges_del(GF_HTML_MediaTimeRanges *ranges)
{
gf_html_timeranges_reset(ranges);
gf_list_del(ranges->times);
ranges->times = NULL;
gf_free(ranges);
}
void gf_html_timeranges_merge(GF_HTML_MediaTimeRanges *ranges) {
u32 i, count;
u64 *start;
u64 *end;
u64 *prev_end;
GF_List *merged = gf_list_new();
prev_end = NULL;
count = gf_list_count(ranges->times);
for (i = 0; i < count; i+=2) {
start = (u64 *)gf_list_get(ranges->times, i);
end = (u64 *)gf_list_get(ranges->times, i+1);
if (prev_end == NULL || *start > *prev_end) {
if (prev_end) {
gf_list_add(merged, prev_end);
}
gf_list_add(merged, start);
} else if (*start == *prev_end) {
gf_free(start);
}
prev_end = end;
}
if (prev_end) {
gf_list_add(ranges->times, prev_end);
}
gf_list_del(ranges->times);
ranges->times = merged;
}
GF_HTML_MediaTimeRanges *gf_html_timeranges_union(GF_HTML_MediaTimeRanges *a, GF_HTML_MediaTimeRanges *b)
{
GF_HTML_MediaTimeRanges *union_ranges;
u32 i, j, count_a, count_b;
union_ranges = gf_html_timeranges_new(a->timescale);
union_ranges->c = a->c;
union_ranges->_this = a->_this;
count_a = gf_list_count(a->times);
if (b) {
count_b = gf_list_count(b->times);
} else {
count_b = 0;
}
if (count_a == 0 && count_b == 0) {
return NULL;
} else if (count_a == 0) {
GF_HTML_MediaTimeRanges *tmp = a;
a = b;
b = tmp;
count_a = count_b;
count_b = 0;
}
i = 0;
j = 0;
while (i < count_a) {
Bool add_a = GF_TRUE;
u64 *starta = (u64 *)gf_list_get(a->times, i);
u64 *enda = (u64 *)gf_list_get(a->times, i+1);
while (j < count_b) {
u64 *startb = (u64 *)gf_list_get(b->times, j);
u64 *endb = (u64 *)gf_list_get(b->times, j+1);
if (*enda*b->timescale < *startb*a->timescale) {
gf_list_add(union_ranges->times, starta);
gf_list_add(union_ranges->times, enda);
add_a = GF_FALSE;
i+=2;
break;
} else if (*endb*a->timescale < *starta*b->timescale) {
*startb = (u64)((*startb * a->timescale)*1.0 / b->timescale);
gf_list_add(union_ranges->times, startb);
*endb = (u64)((*endb * a->timescale)*1.0 / b->timescale);
gf_list_add(union_ranges->times, endb);
j+=2;
} else {
if (*starta*b->timescale <= *startb*a->timescale) {
if (*endb*a->timescale <= *enda*b->timescale) {
j+=2;
} else {
*startb = (u64)((*starta * b->timescale)*1.0 / a->timescale);
i+=2;
break;
}
} else {
if (*enda*b->timescale <= *endb*a->timescale) {
add_a = GF_FALSE;
i+=2;
break;
} else {
*starta = (u64)((*startb * a->timescale)*1.0 / b->timescale);
j+=2;
}
}
}
}
if (add_a == GF_TRUE && i+2 < count_a) {
u64 *next_starta = (u64 *)gf_list_get(a->times, i+2);
if (*enda == *next_starta) {
*next_starta = *starta;
}
add_a = GF_FALSE;
}
if (add_a) {
gf_list_add(union_ranges->times, starta);
gf_list_add(union_ranges->times, enda);
}
i+=2;
}
gf_html_timeranges_merge(union_ranges);
return union_ranges;
}
GF_HTML_MediaTimeRanges *gf_html_timeranges_intersection(GF_HTML_MediaTimeRanges *a, GF_HTML_MediaTimeRanges *b)
{
GF_HTML_MediaTimeRanges *intersection_ranges;
u32 i, j, count_a, count_b;
intersection_ranges = gf_html_timeranges_new(a->timescale);
intersection_ranges->c = a->c;
intersection_ranges->_this = a->_this;
count_a = 0;
count_b = 0;
if (a) count_a = gf_list_count(a->times);
if (b) count_b = gf_list_count(b->times);
if (count_a != 0 && count_b != 0) {
i = 0;
j = 0;
while (i < count_a) {
u64 *starta = (u64 *)gf_list_get(a->times, i);
u64 *enda = (u64 *)gf_list_get(a->times, i+1);
while (j < count_b) {
u64 *startb = (u64 *)gf_list_get(b->times, j);
u64 *endb = (u64 *)gf_list_get(b->times, j+1);
if (*enda*b->timescale < *startb*a->timescale) {
i+=2;
break;
} else if (*endb*a->timescale < *starta*b->timescale) {
j+=2;
} else {
if (*starta*b->timescale <= *startb*a->timescale) {
gf_list_add(intersection_ranges->times, startb);
if (*endb*a->timescale <= *enda*b->timescale) {
gf_list_add(intersection_ranges->times, endb);
*starta = (u64)((*endb * a->timescale)*1.0 / b->timescale);
j+=2;
} else {
gf_list_add(intersection_ranges->times, enda);
*startb = (u64)((*enda * b->timescale)*1.0 / a->timescale);
i+=2;
break;
}
} else {
gf_list_add(intersection_ranges->times, startb);
if (*enda*b->timescale <= *endb*a->timescale) {
gf_list_add(intersection_ranges->times, enda);
*startb = (u64)((*enda * b->timescale)*1.0 / a->timescale);
i+=2;
break;
} else {
gf_list_add(intersection_ranges->times, endb);
*starta = (u64)((*endb * a->timescale)*1.0 / b->timescale);
j+=2;
}
}
}
}
}
}
return intersection_ranges;
}
GF_HTML_Track *html_media_add_new_track_to_list(GF_HTML_TrackList *tracklist,
GF_HTML_TrackType type, const char *mime, Bool enable_or_selected,
const char *id, const char *kind, const char *label, const char *lang)
{
GF_HTML_Track *track;
track = gf_html_media_track_new(type, mime, enable_or_selected, id, kind, label, lang);
gf_list_add(tracklist->tracks, track);
return track;
}
Bool html_media_tracklist_has_track(GF_HTML_TrackList *tracklist, const char *id)
{
GF_HTML_Track *track;
u32 i, count;
count = gf_list_count(tracklist->tracks);
for (i = 0; i < count; i++)
{
track = (GF_HTML_Track *)gf_list_get(tracklist->tracks, i);
if (!strcmp(id, track->id))
{
return 1;
}
}
return 0;
}
GF_HTML_Track *html_media_tracklist_get_track(GF_HTML_TrackList *tracklist, const char *id)
{
GF_HTML_Track *track = NULL;
u32 i, count;
count = gf_list_count(tracklist->tracks);
for (i = 0; i < count; i++)
{
track = (GF_HTML_Track *)gf_list_get(tracklist->tracks, i);
if (!strcmp(id, track->id))
{
return track;
}
}
return NULL;
}
void gf_html_tracklist_del(GF_HTML_TrackList *tlist)
{
while (gf_list_count(tlist->tracks))
{
GF_HTML_Track *track = (GF_HTML_Track *)gf_list_get(tlist->tracks, 0);
gf_html_track_del(track);
gf_list_rem(tlist->tracks, 0);
}
gf_list_del(tlist->tracks);
}
GF_HTML_Track *gf_html_media_track_new(GF_HTML_TrackType type, const char *mime, Bool enable_or_selected,
const char *id, const char *kind, const char *label, const char *lang)
{
GF_HTML_Track *track;
GF_SAFEALLOC(track, GF_HTML_Track);
if (!track) return NULL;
track->type = type;
track->mime = gf_strdup(mime);
track->id = gf_strdup(id);
track->kind = gf_strdup(kind);
track->label = gf_strdup(label);
track->language = gf_strdup(lang);
track->enabled_or_selected = enable_or_selected;
return track;
}
void gf_html_track_del(GF_HTML_Track *track)
{
if (track->id) gf_free(track->id);
if (track->kind) gf_free(track->kind);
if (track->label) gf_free(track->label);
if (track->language) gf_free(track->language);
if (track->mime) gf_free(track->mime);
if (track->buffer_mutex) {
gf_mx_p(track->buffer_mutex);
while (gf_list_count(track->buffer))
{
GF_MSE_Packet *packet = (GF_MSE_Packet *)gf_list_get(track->buffer, 0);
gf_mse_packet_del(packet);
gf_list_rem(track->buffer, 0);
}
gf_mx_v(track->buffer_mutex);
gf_list_del(track->buffer);
gf_mx_del(track->buffer_mutex);
} else {
assert(track->buffer == NULL);
}
gf_free(track);
}
GF_HTML_MediaElement *gf_html_media_element_new(GF_Node *media_node, GF_HTML_MediaController *mc)
{
GF_HTML_MediaElement *me;
GF_SAFEALLOC(me, GF_HTML_MediaElement);
if (!me) return NULL;
me->node = media_node;
me->controller = mc;
me->audioTracks.tracks = gf_list_new();
me->videoTracks.tracks = gf_list_new();
me->textTracks.tracks = gf_list_new();
me->buffered = gf_html_timeranges_new(1);
me->played = gf_html_timeranges_new(1);
me->seekable = gf_html_timeranges_new(1);
return me;
}
void gf_html_media_element_del(GF_HTML_MediaElement *me)
{
if (me->startDate) gf_free(me->startDate);
if (me->currentSrc) gf_free(me->currentSrc);
gf_html_tracklist_del(&me->audioTracks);
gf_html_tracklist_del(&me->videoTracks);
gf_html_tracklist_del(&me->textTracks);
gf_html_timeranges_del(me->buffered);
gf_html_timeranges_del(me->seekable);
gf_html_timeranges_del(me->played);
gf_free(me);
}
GF_HTML_MediaController *gf_html_media_controller_new()
{
GF_HTML_MediaController *mc;
GF_SAFEALLOC(mc, GF_HTML_MediaController);
if (!mc) return NULL;
mc->buffered = gf_html_timeranges_new(1);
mc->played = gf_html_timeranges_new(1);
mc->seekable = gf_html_timeranges_new(1);
return mc;
}
void gf_html_mediacontroller_del(GF_HTML_MediaController *mc)
{
u32 i, count;
count = gf_list_count(mc->media_elements);
for (i = 0; i < count; i++) {
GF_HTML_MediaElement *me = (GF_HTML_MediaElement *)gf_list_get(mc->media_elements, i);
me->controller = NULL;
}
gf_html_timeranges_del(mc->buffered);
gf_html_timeranges_del(mc->seekable);
gf_html_timeranges_del(mc->played);
gf_free(mc);
}
#endif