This source file includes following definitions.
- NewClock
- gf_clock_del
- gf_clock_find
- gf_ck_look_for_clock_dep
- gf_ck_resolve_clock_dep
- gf_clock_attach
- gf_clock_reset
- gf_clock_stop
- gf_clock_set_time
- gf_clock_pause
- gf_clock_resume
- gf_clock_real_time
- gf_clock_time
- gf_clock_media_time
- gf_clock_elapsed_time
- gf_clock_is_started
- gf_clock_buffer_on
- gf_clock_buffer_off
- gf_clock_set_speed
- gf_clock_adjust_drift
- gf_clock_discontinuity
#include <gpac/internal/terminal_dev.h>
GF_Clock *NewClock(GF_Terminal *term)
{
GF_Clock *tmp;
GF_SAFEALLOC(tmp, GF_Clock);
if (!tmp) return NULL;
tmp->mx = gf_mx_new("Clock");
tmp->term = term;
tmp->speed = FIX_ONE;
tmp->data_timeout = term->net_data_timeout;
return tmp;
}
void gf_clock_del(GF_Clock *ck)
{
gf_mx_del(ck->mx);
gf_free(ck);
}
GF_Clock *gf_clock_find(GF_List *Clocks, u16 clockID, u16 ES_ID)
{
u32 i;
GF_Clock *tmp;
i=0;
while ((tmp = (GF_Clock *)gf_list_enum(Clocks, &i))) {
if (tmp->clockID == clockID) return tmp;
if (ES_ID && (tmp->clockID == ES_ID)) return tmp;
}
return NULL;
}
static GF_Clock *gf_ck_look_for_clock_dep(GF_Scene *scene, u16 clockID)
{
u32 i, j;
GF_Channel *ch;
GF_ObjectManager *odm;
i=0;
while ((ch = (GF_Channel*)gf_list_enum(scene->root_od->channels, &i))) {
if (ch->esd->ESID == clockID) return ch->clock;
}
j=0;
while ((odm = (GF_ObjectManager*)gf_list_enum(scene->resources, &j))) {
i=0;
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
if (ch->esd->ESID == clockID) return ch->clock;
}
}
return NULL;
}
static void gf_ck_resolve_clock_dep(GF_List *clocks, GF_Scene *scene, GF_Clock *ck, u16 Clock_ESID)
{
u32 i, j;
GF_Clock *clock;
GF_Channel *ch;
GF_ObjectManager *odm;
i=0;
while ((ch = (GF_Channel*)gf_list_enum(scene->root_od->channels, &i))) {
if (ch->clock->clockID == Clock_ESID) {
if (scene->scene_codec && scene->scene_codec->ck == ch->clock) scene->scene_codec->ck = ck;
if (scene->od_codec && scene->od_codec->ck == ch->clock) scene->od_codec->ck = ck;
#ifndef GPAC_MINIMAL_ODF
if (scene->root_od->oci_codec && scene->root_od->oci_codec->ck == ch->clock) scene->root_od->oci_codec->ck = ck;
#endif
ch->clock = ck;
if (ch->esd) ch->esd->OCRESID = ck->clockID;
}
}
j=0;
while ((odm = (GF_ObjectManager*)gf_list_enum(scene->resources, &j))) {
i=0;
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
if (ch->clock->clockID == Clock_ESID) {
if (odm->codec && (odm->codec->ck==ch->clock)) odm->codec->ck = ck;
#ifndef GPAC_MINIMAL_ODF
if (odm->oci_codec && (odm->oci_codec->ck==ch->clock)) odm->oci_codec->ck = ck;
#endif
ch->clock = ck;
if (ch->esd) ch->esd->OCRESID = ck->clockID;
}
}
}
i=0;
while ((clock = (GF_Clock*)gf_list_enum(clocks, &i))) {
if (clock->clockID == Clock_ESID) {
gf_list_rem(clocks, i-1);
gf_clock_del(clock);
return;
}
}
}
GF_Clock *gf_clock_attach(GF_List *clocks, GF_Scene *scene, u16 clockID, u16 ES_ID, s32 hasOCR)
{
Bool check_dep;
GF_Clock *tmp = gf_clock_find(clocks, clockID, ES_ID);
check_dep = (scene->root_od->net_service && scene->root_od->net_service->Clocks==clocks) ? GF_TRUE : GF_FALSE;
if (!tmp && check_dep) tmp = gf_ck_look_for_clock_dep(scene, clockID);
if (!tmp) {
tmp = NewClock(scene->root_od->term);
tmp->clockID = clockID;
gf_list_add(clocks, tmp);
} else {
if (tmp->clockID == ES_ID) tmp->clockID = clockID;
if (check_dep && (tmp->clockID != ES_ID)) gf_ck_resolve_clock_dep(clocks, scene, tmp, ES_ID);
}
if (hasOCR >= 0) tmp->use_ocr = hasOCR;
return tmp;
}
void gf_clock_reset(GF_Clock *ck)
{
ck->clock_init = 0;
ck->drift = 0;
ck->discontinuity_time = 0;
ck->init_time = 0;
ck->StartTime = 0;
ck->has_seen_eos = 0;
ck->media_time_at_init = 0;
ck->has_media_time_shift = 0;
}
void gf_clock_stop(GF_Clock *ck)
{
ck->clock_init = 0;
ck->StartTime = 0;
}
void gf_clock_set_time(GF_Clock *ck, u32 TS)
{
if (!ck->clock_init) {
ck->init_time = TS;
ck->clock_init = 1;
ck->broken_pcr = 0;
ck->drift = 0;
ck->PauseTime = ck->StartTime = gf_term_get_time(ck->term);
}
}
void gf_clock_pause(GF_Clock *ck)
{
gf_mx_p(ck->mx);
if (!ck->Paused)
ck->PauseTime = gf_term_get_time(ck->term);
ck->Paused += 1;
gf_mx_v(ck->mx);
}
void gf_clock_resume(GF_Clock *ck)
{
gf_mx_p(ck->mx);
assert(ck->Paused);
if (!ck->Paused) {
assert(!ck->Buffering);
}
ck->Paused -= 1;
if (!ck->Paused)
ck->StartTime += gf_term_get_time(ck->term) - ck->PauseTime;
gf_mx_v(ck->mx);
}
u32 gf_clock_real_time(GF_Clock *ck)
{
u32 time;
assert(ck);
if (!ck->clock_init) return ck->StartTime;
time = ck->Paused > 0 ? ck->PauseTime : gf_term_get_time(ck->term);
#ifdef GPAC_FIXED_POINT
if ((ck->speed < 0) && ((s32) ck->init_time < FIX2INT( (-ck->speed * 100) * (time - ck->StartTime)) / 100 ) ) {
time = 0;
} else {
time = ck->discontinuity_time + ck->init_time + (time - ck->StartTime) * FIX2INT(100*ck->speed) / 100;
}
#else
if ((ck->speed < 0) && ((s32) ck->init_time < (-ck->speed) * (time - ck->StartTime))) {
time = 0;
} else {
time = ck->discontinuity_time + ck->init_time + (u32) (ck->speed * (time - ck->StartTime) );
}
#endif
return time;
}
GF_EXPORT
u32 gf_clock_time(GF_Clock *ck)
{
u32 time = gf_clock_real_time(ck);
if ((ck->drift>0) && (time < (u32) ck->drift)) return 0;
return time - ck->drift;
}
u32 gf_clock_media_time(GF_Clock *ck)
{
u32 t;
if (!ck) return 0;
if (!ck->has_seen_eos && ck->last_TS_rendered) t = ck->last_TS_rendered;
else t = gf_clock_time(ck);
if (ck->has_media_time_shift) {
if (t>ck->init_time) t -= ck->init_time;
else t=0;
t += ck->media_time_at_init;
}
return t;
}
u32 gf_clock_elapsed_time(GF_Clock *ck)
{
if (!ck || ck->Buffering || ck->Paused) return 0;
return gf_sys_clock() - ck->StartTime;
}
Bool gf_clock_is_started(GF_Clock *ck)
{
if (!ck || ck->Buffering || ck->Paused) return 0;
return 1;
}
void gf_clock_buffer_on(GF_Clock *ck)
{
gf_mx_p(ck->mx);
if (!ck->Buffering) gf_clock_pause(ck);
ck->Buffering += 1;
gf_mx_v(ck->mx);
}
void gf_clock_buffer_off(GF_Clock *ck)
{
gf_mx_p(ck->mx);
if (ck->Buffering) {
ck->Buffering -= 1;
if (!ck->Buffering) gf_clock_resume(ck);
}
gf_mx_v(ck->mx);
}
void gf_clock_set_speed(GF_Clock *ck, Fixed speed)
{
u32 time;
if (speed==ck->speed) return;
time = gf_term_get_time(ck->term);
ck->discontinuity_time = gf_clock_time(ck) - ck->init_time;
ck->PauseTime = ck->StartTime = time;
ck->speed = speed;
}
void gf_clock_adjust_drift(GF_Clock *ck, s32 ms_drift)
{
if (ck) ck->drift = ms_drift;
}
void gf_clock_discontinuity(GF_Clock *ck, GF_Scene *scene, Bool is_pcr_discontinuity)
{
u32 i, j;
GF_Channel *ch;
GF_ObjectManager *odm;
i=0;
while ((ch = (GF_Channel*)gf_list_enum(scene->root_od->channels, &i))) {
if (ch->clock == ck) {
gf_es_reset_timing(ch, is_pcr_discontinuity);
}
}
j=0;
while ((odm = (GF_ObjectManager*)gf_list_enum(scene->resources, &j))) {
if (odm->state==GF_ODM_STATE_STOP)
continue;
i=0;
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
if (ch->clock == ck) {
gf_es_reset_timing(ch, is_pcr_discontinuity);
ch->CTS = ch->DTS = 0;
GF_LOG(GF_LOG_WARNING, GF_LOG_SYNC, ("[SyncLayer] Reinitializing timing for ES%d\n", ch->esd->ESID));
if (ch->odm->codec && ch->odm->codec->CB)
gf_cm_reset_timing(ch->odm->codec->CB);
}
}
}
gf_scene_reset_addons(scene);
if (ck->has_media_time_shift) {
u32 new_media_time = ck->media_time_at_init + gf_clock_time(ck) - ck->init_time;
gf_clock_reset(ck);
ck->has_media_time_shift = 1;
ck->media_time_at_init = new_media_time;
} else {
gf_clock_reset(ck);
}
}