/*access to the first available CU for rendering this is a blocking call since input may change the output (temporal scalability)*/ GF_CMUnit *gf_cm_get_output(GF_CompositionMemory *cb) { GF_CMUnit *out = NULL; /*if paused or stop or buffering, do nothing*/ switch (cb->Status) { case CB_BUFFER: return NULL; case CB_STOP: case CB_PAUSE: /*only visual buffers deliver data when paused*/ if (cb->odm->codec->type != GF_STREAM_VISUAL) goto exit; break; case CB_BUFFER_DONE: cb->Status = CB_PLAY; break; } /*no output*/ if (!cb->output->dataLength) { if ((cb->Status != CB_STOP) && cb->HasSeenEOS && (cb->odm && cb->odm->codec)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time)); cb->Status = CB_STOP; cb->odm->current_time = (u32) cb->odm->media_stop_time; #ifndef GPAC_DISABLE_VRML /*force update of media time*/ mediasensor_update_timing(cb->odm, 1); #endif } goto exit; } /*update the timing*/ if ((cb->Status != CB_STOP) && cb->odm && cb->odm->codec) { cb->odm->current_time = cb->output->TS; /*handle visual object - EOS if no more data (we keep the last CU for rendering, so check next one)*/ if (cb->HasSeenEOS && (!cb->output->next->dataLength || (cb->Capacity==1))) { GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time)); cb->Status = CB_STOP; cb->odm->current_time = (u32) cb->odm->media_stop_time; #ifndef GPAC_DISABLE_VRML /*force update of media time*/ mediasensor_update_timing(cb->odm, 1); #endif gf_odm_signal_eos(cb->odm); } } out = cb->output; //assert(out->TS >= cb->LastRenderedTS); exit: return out; }
void gf_cm_set_eos(GF_CompositionMemory *cb) { gf_odm_lock(cb->odm, 1); /*we may have a pb if the stream is so short that the EOS is signaled while we're buffering. In this case we shall turn the clock on and keep a trace of the EOS notif*/ if (cb->Status == CB_BUFFER) { cb->Status = CB_BUFFER_DONE; gf_clock_buffer_off(cb->odm->codec->ck); GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB EOS - ODM%d: buffering off at OTB %u (STB %d) (nb wait on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_clock_time(cb->odm->codec->ck), gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering)); } cb->HasSeenEOS = 1; //in bench mode eos cannot be signaled through flush of composition memory since it is always empty - do it here if (cb->odm->term->bench_mode==2) { cb->Status = CB_STOP; gf_odm_signal_eos(cb->odm); } gf_term_invalidate_compositor(cb->odm->term); gf_odm_lock(cb->odm, 0); }
/*access to the first available CU for rendering this is a blocking call since input may change the output (temporal scalability)*/ GF_CMUnit *gf_cm_get_output(GF_CompositionMemory *cb) { /*if paused or stop or buffering, do nothing*/ switch (cb->Status) { case CB_BUFFER: case CB_STOP: /*only visual buffers deliver data when buffering or stop*/ if (cb->odm->codec->type != GF_STREAM_VISUAL) return NULL; break; case CB_BUFFER_DONE: //For non-visual output move to play state upon fetch if (cb->odm->codec->type != GF_STREAM_VISUAL) cb->Status = CB_PLAY; break; //we always deliver in pause, up to the caller to decide to consume or not the frame case CB_PAUSE: break; } /*no output*/ if (!cb->UnitCount || !cb->output->dataLength) { if ((cb->Status != CB_STOP) && cb->HasSeenEOS && (cb->odm && cb->odm->codec)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time)); if ((cb->Status==CB_BUFFER_DONE) && (cb->odm->codec->type == GF_STREAM_VISUAL) ){ gf_clock_buffer_off(cb->odm->codec->ck); } cb->Status = CB_STOP; cb->odm->media_current_time = (u32) cb->odm->media_stop_time; #ifndef GPAC_DISABLE_VRML /*force update of media time*/ mediasensor_update_timing(cb->odm, 1); #endif gf_odm_signal_eos(cb->odm); } return NULL; } /*update the timing*/ if ((cb->Status != CB_STOP) && cb->odm && cb->odm->codec) { if (cb->odm->codec->ck->has_media_time_shift) { cb->odm->media_current_time = cb->output->TS + cb->odm->codec->ck->media_time_at_init - cb->odm->codec->ck->init_time; } else { cb->odm->media_current_time = cb->output->TS; } /*handle visual object - EOS if no more data (we keep the last CU for rendering, so check next one)*/ if (cb->HasSeenEOS && (cb->odm->codec->type == GF_STREAM_VISUAL) && (!cb->output->next->dataLength || (cb->Capacity==1))) { GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time)); if (cb->Status==CB_BUFFER_DONE) { gf_clock_buffer_off(cb->odm->codec->ck); } cb->Status = CB_STOP; cb->odm->media_current_time = (u32) cb->odm->media_stop_time; #ifndef GPAC_DISABLE_VRML /*force update of media time*/ mediasensor_update_timing(cb->odm, 1); #endif gf_odm_signal_eos(cb->odm); } } if (cb->output->sender_ntp) { cb->LastRenderedNTPDiff = gf_net_get_ntp_diff_ms(cb->output->sender_ntp); cb->LastRenderedNTP = cb->output->sender_ntp; } return cb->output; }