Beispiel #1
0
MediaControlStack *gf_odm_get_mediacontrol(GF_ObjectManager *odm)
{
	GF_Clock *ck;
	ck = gf_odm_get_media_clock(odm);
	if (!ck) return NULL;
	return ck->mc;
}
Beispiel #2
0
/*pause all objects*/
void MC_SetSpeed(GF_ObjectManager *odm, Fixed speed)
{
	u32 i;
	GF_ObjectManager *ctrl_od;
	GF_Scene *in_scene;
	GF_Clock *ck;

	if (odm->flags & GF_ODM_NO_TIME_CTRL) return;

	/*locate all objects sharing the clock*/
	ck = gf_odm_get_media_clock(odm);
	if (!ck) return;

	in_scene = odm->parentscene;
	if (odm->subscene) {
		assert(odm->subscene->root_od==odm);
//		assert( gf_odm_shares_clock(odm, ck) );
		gf_odm_set_speed(odm, speed, GF_TRUE);
		in_scene = odm->subscene;
	}

	i=0;
	while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
		if (!gf_odm_shares_clock(ctrl_od, ck)) continue;
		gf_odm_set_speed(ctrl_od, speed, GF_TRUE);
	}
}
Beispiel #3
0
GF_EXPORT
void gf_service_download_update_stats(GF_DownloadSession * sess)
{
	GF_ClientService *serv;
	const char *szURI;
	u32 total_size, bytes_done, bytes_per_sec;
	GF_NetIOStatus net_status;

	if (!sess) return;

	gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status);
	serv = (GF_ClientService *)gf_dm_sess_get_private(sess);
	switch (net_status) {
	case GF_NETIO_SETUP:
		gf_term_message(serv->term, serv->url, "Connecting", GF_OK);
		break;
	case GF_NETIO_CONNECTED:
		gf_term_message(serv->term, serv->url, "Connected", GF_OK);
		break;
	case GF_NETIO_WAIT_FOR_REPLY:
		gf_term_message(serv->term, serv->url, "Waiting for reply...", GF_OK);
		break;
	case GF_NETIO_PARSE_REPLY:
		gf_term_message(serv->term, serv->url, "Starting download...", GF_OK);
		break;
	case GF_NETIO_DATA_EXCHANGE:
		/*notify some connection / ...*/
		if (total_size) {
			GF_Event evt;
			evt.type = GF_EVENT_PROGRESS;
			evt.progress.progress_type = 1;
			evt.progress.service = szURI;
			evt.progress.total = total_size;
			evt.progress.done = bytes_done;
			evt.progress.bytes_per_seconds = bytes_per_sec;
			gf_term_send_event(serv->term, &evt);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size));
		gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec);
		break;
	case GF_NETIO_DATA_TRANSFERED:
		gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE);
		if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			if (!gf_clock_is_started(ck)) {
				GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n"));
				if (serv->is_paused) {
					serv->is_paused = 0;
#ifndef GPAC_DISABLE_VRML
					mediacontrol_resume(serv->owner, 0);
#endif
				}
			}
		}
		break;
	default:
		break;
	}
}
Beispiel #4
0
Bool gf_odm_check_segment_switch(GF_ObjectManager *odm)
{
	u32 count, i;
	GF_Segment *cur, *next;
	MediaControlStack *ctrl = gf_odm_get_mediacontrol(odm);

	/*if no control or control not on this object ignore segment switch*/
	if (!ctrl || (ctrl->stream->odm != odm)) return 0;

	count = gf_list_count(ctrl->seg);
	/*reached end of controled stream (no more segments)*/
	if (ctrl->current_seg>=count) return 0;

	/*synth media, trigger if end of segment run-time*/
	if (!odm->codec || ((odm->codec->type!=GF_STREAM_VISUAL) && (odm->codec->type!=GF_STREAM_AUDIO))) {
		GF_Clock *ck = gf_odm_get_media_clock(odm);
		u32 now = gf_clock_time(ck);
		u64 dur = odm->subscene ? odm->subscene->duration : odm->duration;
		cur = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg);
		if (odm->subscene && odm->subscene->needs_restart) return 0;
		if (cur) dur = (u32) ((cur->Duration+cur->startTime)*1000);
		if (now<=dur) return 0;
	} else {
		/*FIXME - for natural media with scalability, we should only process when all streams of the object are done*/
	}

	/*get current segment and move to next one*/
	cur = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg);
	ctrl->current_seg ++;

	/*resync in case we have been issuing a play range over several segments*/
	for (i=ctrl->current_seg; i<count; i++) {
		next = (GF_Segment *)gf_list_get(ctrl->seg, i);
		if (
		    /*if next seg start is after cur seg start*/
		    (cur->startTime < next->startTime)
		    /*if next seg start is before cur seg end*/
		    && (cur->startTime + cur->Duration > next->startTime)
		    /*if next seg start is already passed*/
		    && (1000*next->startTime < odm->media_current_time)
		    /*then next segment was taken into account when requesting play*/
		) {
			cur = next;
			ctrl->current_seg ++;
		}
	}
	/*if last segment in ctrl is done, end of stream*/
	if (ctrl->current_seg >= count) return 0;
	next = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg);

	/*if next seg start is not in current seg, media needs restart*/
	if ((next->startTime < cur->startTime) || (cur->startTime + cur->Duration < next->startTime))
		mediacontrol_restart(odm);

	return 1;
}
Beispiel #5
0
/*pause all objects*/
void mediacontrol_set_speed(GF_ObjectManager *odm, Fixed speed)
{
    u32 i;
    GF_ObjectManager *ctrl_od;
    GF_Scene *in_scene;
    GF_Clock *ck;

    if (odm->flags & GF_ODM_NO_TIME_CTRL) return;

    /*locate all objects sharing the clock*/
    ck = gf_odm_get_media_clock(odm);
    if (!ck) return;

    in_scene = odm->parentscene;
    if (odm->subscene) {
        assert(odm->subscene->root_od==odm);
        in_scene = odm->subscene;

        //dynamic scene with speed direction, we need to re-start everything to issue new PLAY requests
        if (in_scene->is_dynamic_scene && (gf_mulfix(ck->speed, speed) < 0)) {
            u32 time = gf_clock_time(ck);
            gf_clock_set_speed(ck, speed);

            //enable main addon
            if (speed<0) {
                i=0;
                while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
                    if (ctrl_od->addon && (ctrl_od->addon->addon_type==GF_ADDON_TYPE_MAIN)) {
                        gf_scene_select_main_addon(in_scene, ctrl_od, GF_TRUE, gf_clock_time(ck) );
                        break;
                    }
                }
            }
            gf_scene_restart_dynamic(in_scene, time, 0, 1);
            return;
        }
        gf_clock_set_speed(ck, speed);
        gf_odm_set_speed(odm, speed, GF_TRUE);
    }

    i=0;
    while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
        if (!gf_odm_shares_clock(ctrl_od, ck)) continue;

        if (ctrl_od->subscene) {
            mediacontrol_set_speed(ctrl_od, speed);
        } else {
            gf_odm_set_speed(ctrl_od, speed, GF_TRUE);
        }
    }
}
Beispiel #6
0
/*pause all objects*/
void mediacontrol_pause(GF_ObjectManager *odm)
{
    u32 i;
    GF_ObjectManager *ctrl_od;
    GF_Scene *in_scene;
    GF_Clock *ck;

    if (odm->flags & GF_ODM_NO_TIME_CTRL) return;

    /*otherwise locate all objects sharing the clock*/
    ck = gf_odm_get_media_clock(odm);
    if (!ck) {
        odm->flags |= GF_ODM_PAUSE_QUEUED;
        return;
    }

    in_scene = odm->parentscene;
    if (odm->subscene) {
        assert(odm->subscene->root_od==odm);
        assert(odm->subscene->is_dynamic_scene || gf_odm_shares_clock(odm, ck) );
        /*pause root*/
        gf_odm_pause(odm);
        in_scene = odm->subscene;
    }

    i=0;
    while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
        if (!odm->subscene && !gf_odm_shares_clock(ctrl_od, ck))
            continue;

        if (ctrl_od->addon && (ctrl_od->addon->addon_type==GF_ADDON_TYPE_MAIN)) {
            gf_clock_pause(ck);
            gf_scene_select_main_addon(in_scene, ctrl_od, GF_TRUE, gf_clock_time(ck) );
        }

        if (ctrl_od->subscene) {
            mediacontrol_pause(ctrl_od);
        } else {
            gf_odm_pause(ctrl_od);
        }
    }
}
Beispiel #7
0
static void gf_inline_check_restart(GF_Scene *scene)
{
	/*no ctrl if no duration*/
	if (!scene->duration) return;
	if (!scene->needs_restart) gf_odm_check_segment_switch(scene->root_od);
	if (scene->needs_restart) return;

	if (scene->root_od->media_ctrl && scene->root_od->media_ctrl->control->loop) {
		GF_Clock *ck = gf_odm_get_media_clock(scene->root_od);
		if (ck->has_seen_eos) {
			u32 now = gf_clock_time(ck);
			u64 dur = scene->duration;
			if (scene->root_od->media_ctrl->current_seg) {
				/*only process when all segments are played*/
				if (gf_list_count(scene->root_od->media_ctrl->seg) <= scene->root_od->media_ctrl->current_seg) {
					scene->needs_restart = 1;
					scene->root_od->media_ctrl->current_seg = 0;
				}
			}
			else {
				Double s, e;
				s = now;
				s/=1000;
				e = -1;
				MC_GetRange(scene->root_od->media_ctrl, &s, &e);
				if ((e>=0) && (e<GF_MAX_FLOAT)) dur = (u32) (e*1000);
				if (dur<=now) {
					scene->needs_restart = 1;
					scene->root_od->media_ctrl->current_seg = 0;
				} else {
					/*trigger render until to watch for restart...*/
					gf_term_invalidate_compositor(scene->root_od->term);
				}
			}
		} else {
			/*trigger render until to watch for restart...*/
			gf_term_invalidate_compositor(scene->root_od->term);
		}
	}
}
Beispiel #8
0
GF_EXPORT
GF_Err gf_term_get_object_info(GF_Terminal *term, GF_ObjectManager *odm, GF_MediaInfo *info)
{
    GF_Channel *ch;

    if (!term || !odm || !odm->OD || !info) return GF_BAD_PARAM;
    if (!gf_term_check_odm(term, odm)) return GF_BAD_PARAM;

    memset(info, 0, sizeof(GF_MediaInfo));
    info->od = odm->OD;

    info->duration = (Double) (s64)odm->duration;
    info->duration /= 1000;
    if (odm->codec) {
        /*since we don't remove ODs that failed setup, check for clock*/
        if (odm->codec->ck) info->current_time = odm->codec->CB ? odm->current_time : gf_clock_time(odm->codec->ck);
        info->current_time /= 1000;
        info->nb_droped = odm->codec->nb_droped;
    } else if (odm->subscene) {
        if (odm->subscene->scene_codec) {
            if (odm->subscene->scene_codec->ck) {
                info->current_time = gf_clock_time(odm->subscene->scene_codec->ck);
                info->current_time /= 1000;
            }
            info->duration = (Double) (s64)odm->subscene->duration;
            info->duration /= 1000;
            info->nb_droped = odm->subscene->scene_codec->nb_droped;
        } else if (odm->subscene->is_dynamic_scene && odm->subscene->dyn_ck) {
            info->current_time = gf_clock_time(odm->subscene->dyn_ck);
            info->current_time /= 1000;
        }
    }

    info->buffer = -2;
    info->db_unit_count = 0;

    /*Warning: is_open==2 means object setup, don't check then*/
    if (odm->state==GF_ODM_STATE_IN_SETUP) {
        info->status = 3;
    } else if (odm->state==GF_ODM_STATE_BLOCKED) {
        info->status = 0;
        info->protection = 2;
    } else if (odm->state) {
        u32 i, buf;
        GF_Clock *ck;

        ck = gf_odm_get_media_clock(odm);
        /*no clock means setup failed*/
        if (!ck) {
            info->status = 4;
        } else {
            info->status = gf_clock_is_started(ck) ? 1 : 2;
            info->clock_drift = ck->drift;

            info->buffer = -1;
            buf = 0;
            i=0;
            while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
                info->db_unit_count += ch->AU_Count;
                if (!ch->is_pulling) {
                    if (ch->MaxBuffer) info->buffer = 0;
                    buf += ch->BufferTime;
                }
                if (ch->is_protected) info->protection = ch->ipmp_tool ? 1 : 2;

            }
            if (buf) info->buffer = (s32) buf;
        }
    }

    info->has_profiles = (odm->flags & GF_ODM_HAS_PROFILES) ? 1 : 0;
    if (info->has_profiles) {
        info->inline_pl = (odm->flags & GF_ODM_INLINE_PROFILES) ? 1 : 0;
        info->OD_pl = odm->OD_PL;
        info->scene_pl = odm->Scene_PL;
        info->audio_pl = odm->Audio_PL;
        info->visual_pl = odm->Visual_PL;
        info->graphics_pl = odm->Graphics_PL;
    }

    if (odm->net_service) {
        info->service_handler = odm->net_service->ifce->module_name;
        info->service_url = odm->net_service->url;
        if (odm->net_service->owner == odm) info->owns_service = 1;
    } else if ((odm->subscene && odm->subscene->graph_attached) || (odm->codec)) {
        info->service_url = "No associated network Service";
    } else {
        info->service_url = "Service not found or error";
    }

    if (odm->codec && odm->codec->decio) {
        if (!odm->codec->decio->GetName) {
            info->codec_name = odm->codec->decio->module_name;
        } else {
            info->codec_name = odm->codec->decio->GetName(odm->codec->decio);
        }
        info->od_type = odm->codec->type;
        if (odm->codec->CB) {
            info->cb_max_count = odm->codec->CB->Capacity;
            info->cb_unit_count = odm->codec->CB->UnitCount;
        }
    }

    if (odm->subscene && odm->subscene->scene_codec) {
        GF_BaseDecoder *dec = odm->subscene->scene_codec->decio;
        assert(odm->subscene->root_od==odm) ;
        info->od_type = odm->subscene->scene_codec->type;
        if (!dec->GetName) {
            info->codec_name = dec->module_name;
        } else {
            info->codec_name = dec->GetName(dec);
        }
        gf_sg_get_scene_size_info(odm->subscene->graph, &info->width, &info->height);
    } else if (odm->mo) {
        switch (info->od_type) {
        case GF_STREAM_VISUAL:
            gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, &info->par, &info->pixelFormat, NULL);
            break;
        case GF_STREAM_AUDIO:
            gf_mo_get_audio_info(odm->mo, &info->sample_rate, &info->bits_per_sample, &info->num_channels, NULL);
            info->clock_drift = 0;
            break;
        case GF_STREAM_TEXT:
            gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, NULL, NULL, NULL);
            break;
        }
    }
    if (odm->subscene && odm->subscene->scene_codec) get_codec_stats(odm->subscene->scene_codec, info);
    else if (odm->codec) get_codec_stats(odm->codec, info);

    ch = (GF_Channel*)gf_list_get(odm->channels, 0);
    if (ch && ch->esd->langDesc) info->lang = ch->esd->langDesc->langCode;

    if (odm->mo && odm->mo->URLs.count)
        info->media_url = odm->mo->URLs.vals[0].url;
    return GF_OK;
}
Beispiel #9
0
GF_EXPORT
void gf_term_download_update_stats(GF_DownloadSession * sess)
{
	GF_ClientService *serv;
	const char *szURI;
	u32 total_size, bytes_done, net_status, bytes_per_sec;

	if (!sess) return;

	gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status);
	serv = (GF_ClientService *)gf_dm_sess_get_private(sess);
	switch (net_status) {
	case GF_NETIO_SETUP:
		gf_term_on_message(serv, GF_OK, "Connecting");
		break;
	case GF_NETIO_CONNECTED:
		gf_term_on_message(serv, GF_OK, "Connected");
		break;
	case GF_NETIO_WAIT_FOR_REPLY:
		gf_term_on_message(serv, GF_OK, "Waiting for reply...");
		break;
	case GF_NETIO_PARSE_REPLY:
		gf_term_on_message(serv, GF_OK, "Starting download...");
		break;
	case GF_NETIO_DATA_EXCHANGE:
		/*notify some connection / ...*/
		if (total_size) {
			GF_Event evt;
			evt.type = GF_EVENT_PROGRESS;
			evt.progress.progress_type = 1;
			evt.progress.service = szURI;
			evt.progress.total = total_size;
			evt.progress.done = bytes_done;
			evt.progress.bytes_per_seconds = bytes_per_sec;
			gf_term_send_event(serv->term, &evt);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size));
		gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec);

		/*JLF fix this*/
		if (0&& (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			Double download_percent, playback_percent, adj_percent;
			download_percent = 100 * bytes_done;
			download_percent /= total_size;

			playback_percent = 100 * serv->owner->current_time;
			playback_percent /= serv->owner->duration;
			if (serv->auto_rebuffer)
				adj_percent = 0.0;
			else
				adj_percent = 100.0 * serv->download_rebuffer / serv->owner->duration;

			if (playback_percent >= download_percent) {
				if (gf_clock_is_started(ck)) {
					GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% but downloaded %d %% - Pausing\n", (u32) playback_percent, (u32) download_percent));
					if (!serv->is_paused) {
						serv->is_paused = 1;
						mediacontrol_pause(serv->owner);
					}
					gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_WAITING);
					gf_term_on_message(serv, GF_OK, "HTTP Buffering ...");
				}
			} else if (playback_percent + adj_percent <= download_percent) {
				Double time_to_play = 0;
				Double time_to_download = 0;
				/*automatic rebuffer: make sure we can finish playback before resuming*/
				if (serv->auto_rebuffer) {
					if (bytes_per_sec) {
						time_to_download = 1000.0*(total_size - bytes_done);
						time_to_download /= bytes_per_sec;
					}
					time_to_play = (Double) serv->owner->duration;
					time_to_play -= serv->owner->current_time;
				}
				if ((time_to_download<=time_to_play) && !gf_clock_is_started(ck)) {
					GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% and downloaded %d %% - Resuming\n", (u32) playback_percent, (u32) download_percent));
					if (serv->auto_rebuffer) {
						GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Auto-rebuffer done: should be done downloading in %d ms and remains %d ms to play\n", (u32) time_to_download, (u32) (serv->owner->duration - serv->owner->current_time) ));
					}
					gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_PLAYING);
					if (serv->is_paused) {
						serv->is_paused = 0;
						mediacontrol_resume(serv->owner);
					}
					gf_term_on_message(serv, GF_OK, "HTTP Resuming playback");
				}
			}
		}
		break;
	case GF_NETIO_DATA_TRANSFERED:
		gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE);
		if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			if (!gf_clock_is_started(ck)) {
				GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n"));
				if (serv->is_paused) {
					serv->is_paused = 0;
					mediacontrol_resume(serv->owner);
				}
			}
		}
		break;
	}
}
Beispiel #10
0
void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos)
{
	GF_Segment *desc;
	u32 i, count, j, ms_count;
	Double time;
	ms_count = gf_list_count(odm->ms_stack);
	if (!ms_count) return;
	
	time = odm->current_time / 1000.0;
	//dirty hack to get timing of frame when very late (openhevc debug)
	if (odm->subscene && odm->subscene->dyn_ck && odm->subscene->dyn_ck->last_TS_rendered)
		time = odm->subscene->dyn_ck->last_TS_rendered / 1000.0;

	for (j=0; j<ms_count; j++) {
		MediaSensorStack *media_sens = (MediaSensorStack *)gf_list_get(odm->ms_stack, j);
		if (!media_sens->is_init) continue;
		count = gf_list_count(media_sens->seg);
		
		/*full object controled*/
		if (!media_sens->active_seg && !count) {
			/*check for end of scene (MediaSensor on inline)*/
			if (odm->subscene && odm->subscene->duration) {
				GF_Clock *ck = gf_odm_get_media_clock(odm);
				if (ck->has_seen_eos && (1000*time>=(Double) (s64)odm->subscene->duration)) {
					if (media_sens->sensor->isActive) {
						/*force notification of time (ntify the scene duration rather than the current clock*/
						media_sens->sensor->mediaCurrentTime = (Double) odm->subscene->duration;
						media_sens->sensor->mediaCurrentTime /= 1000;
						gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
						media_sens->sensor->isActive = 0;
						gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);

						GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", odm->OD->objectDescriptorID));
					}
					continue;
				}
			}

			if (!is_eos && !media_sens->sensor->isActive) {
				media_sens->sensor->isActive = 1;
				gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);

				gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
				if (odm->subscene) {
					media_sens->sensor->mediaDuration = (Double) (s64)odm->subscene->duration;
				} else {
					media_sens->sensor->mediaDuration = (Double) (s64)odm->duration;
				}
				if (media_sens->sensor->mediaDuration)
					media_sens->sensor->mediaDuration /= 1000;
				else
					media_sens->sensor->mediaDuration = -FIX_ONE;

				gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
			}

			if (is_eos && media_sens->sensor->isActive) {
				if (media_sens->sensor->mediaDuration>=0) {
					media_sens->sensor->mediaCurrentTime = media_sens->sensor->mediaDuration;
				} else {
					media_sens->sensor->mediaCurrentTime = time;
				}
				gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
				media_sens->sensor->isActive = 0;
				gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
			} else {
				if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) {
					media_sens->sensor->mediaCurrentTime = time;
					gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
				}
			}
			continue;
		}

		/*locate segment*/
		for (i=media_sens->active_seg; i<count; i++) {
			desc = (GF_Segment*)gf_list_get(media_sens->seg, i);
			/*not controled*/
			if (desc->startTime > time) {
				if (media_sens->sensor->isActive) {
					media_sens->sensor->isActive = 0;
					gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);

					GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName));
				}
				continue;
			}
			if (desc->startTime + desc->Duration < time) continue;
			if (desc->startTime + desc->Duration == time) {
				continue;
			}
			/*segment switch, force activation (isActive TRUE send at each seg)*/
			if (media_sens->active_seg != i) {
				media_sens->active_seg = i;
				media_sens->sensor->isActive = 0;
			}

			if (!media_sens->sensor->isActive) {
				media_sensor_activate(media_sens, desc);

				GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Activating media sensor time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName));
			}

			/*set media time - relative to segment start time*/
			time -= desc->startTime;
			if (media_sens->sensor->mediaCurrentTime != time) {
				media_sens->sensor->mediaCurrentTime = time;
				gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
			}
			break;
		}
		if (i==count) {
			/*we're after last segment, deactivate*/
			if (media_sens->sensor->isActive) {
				media_sens->sensor->isActive = 0;
				gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
				media_sens->active_seg = count;
				GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g: no more segments\n", odm->OD->objectDescriptorID, time));
			}
		}
	}
}
Beispiel #11
0
void mediacontrol_restart(GF_ObjectManager *odm)
{
	GF_List *to_restart;
	GF_ObjectManager *ctrl_od;
	GF_Clock *ck, *scene_ck;
	u32 i;
	u32 current_seg;
#ifndef GPAC_DISABLE_VRML
	MediaControlStack *ctrl;
#endif

	if (!odm || (odm->flags & GF_ODM_NO_TIME_CTRL) ) return;

#ifndef GPAC_DISABLE_VRML
	ctrl = gf_odm_get_mediacontrol(odm);
	if (ctrl) {
		/*we have a control - filter calls to only handle objects owning media control*/
		ctrl_od = ctrl->stream->odm;
		/*if media control owns the scene this OD refers to the scene is always restarted - TODO make that an option*/
		if (!ctrl_od->subscene) {
			if (ctrl->stream->odm != odm) return;
		}
		odm = ctrl->stream->odm;

		/*this is inline restart - only possible through media control*/
		if (odm->subscene && odm->subscene->root_od==ctrl->stream->odm) {
			gf_inline_restart(odm->subscene);
			return;
		}
	}
#endif

	/*if clock is main scene clock do nothing*/
	scene_ck = gf_odm_get_media_clock(odm->parentscene->root_od);
	if (gf_odm_shares_clock(odm, scene_ck)) {
		if (odm->parentscene->is_dynamic_scene)
			gf_scene_restart_dynamic(odm->parentscene, 0, 0);
		return;
	}

	/*otherwise locate all objects sharing the clock*/
	ck = gf_odm_get_media_clock(odm);
	if (!ck) return;

	current_seg = 0;
#ifndef GPAC_DISABLE_VRML
	/*store current segment idx*/
	if (ctrl) {
		current_seg = ctrl->current_seg;
		/*if last segment is passed restart*/
		if (gf_list_count(ctrl->seg) == current_seg) current_seg = 0;
	}
#endif

	to_restart = gf_list_new();
	/*do stop/start in 2 pass, it's much cleaner for servers*/
	i=0;
	while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(odm->parentscene->resources, &i))) {
		if (!gf_odm_shares_clock(ctrl_od, ck)) continue;
		/*if running, stop and collect for restart*/
		if (ctrl_od->state) {
			gf_odm_stop(ctrl_od, 1);
			gf_list_add(to_restart, ctrl_od);
		}
	}
	/*force clock reset since we don't know how OD ordering is done*/
	gf_clock_reset(ck);
#ifndef GPAC_DISABLE_VRML
	if (ctrl) ctrl->current_seg = current_seg;
#endif

	/*play on all ODs collected for restart*/
	i=0;
	while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(to_restart, &i))) {
		gf_odm_start(ctrl_od, 0);
	}
	gf_list_del(to_restart);
}
Beispiel #12
0
void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool shall_restart, need_restart;
	GF_MediaObject *prev;
	GF_ObjectManager *odm;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	MediaControlStack *stack =(MediaControlStack *) gf_node_get_private(node);

	if (is_destroy) {
		GF_ObjectManager *odm;
		MediaControlStack *stack = (MediaControlStack *) gf_node_get_private(node);

		/*reset ODM using this control*/
		if (stack->stream) {
			if (stack->stream->odm) {
				odm = stack->stream->odm;
				gf_odm_remove_mediacontrol(odm, stack);
			}
			/*also removes the association ck<->MC if the object has been destroyed before the node*/
			if (stack->ck) stack->ck->mc = NULL;
		}
		gf_list_del(stack->seg);
		gf_sg_vrml_mf_reset(&stack->url, GF_SG_VRML_MFURL);
		gf_free(stack);
		return;
	}
	//we need to disable culling otherwise we may never be called back again ...
	tr_state->disable_cull = 1;

	/*not changed nothing to do - note we need to register with stream yet for control switching...*/
	if (stack->stream && (!stack->changed || !stack->control->enabled)) return;

	need_restart = (stack->changed==2) ? 1 : 0;
	shall_restart = (stack->control->mediaStartTime>=0) ? 1 : 0;

	/*check url target*/
	if (stack->stream) {
		if (MC_URLChanged(&stack->url, &stack->control->url)) {
			gf_sg_vrml_mf_reset(&stack->url, GF_SG_VRML_MFURL);

			prev = stack->stream;
			if (gf_list_find(stack->parent->scene_objects, prev)<0)
				prev = NULL;

			stack->stream = gf_scene_get_media_object(stack->parent, &stack->control->url, GF_MEDIA_OBJECT_UNDEF, 0);
			if (stack->stream) {
				if (!stack->stream->odm) return;
				/*MediaControl on inline: if dynamic scene, make sure it is connected before attaching...*/
				if (stack->stream->odm->subscene) {
					if (stack->stream->odm->subscene->is_dynamic_scene && !stack->stream->odm->subscene->dyn_ck) return;
				}
				gf_sg_vrml_field_copy(&stack->url, &stack->control->url, GF_SG_VRML_MFURL);

				/*remove from prev*/
				if (prev && prev->odm && (prev != stack->stream)) gf_odm_remove_mediacontrol(prev->odm, stack);
				/*register with new*/
				/*if we assigned the media control to an exiting object - force the state of the object*/
				gf_odm_set_mediacontrol((GF_ObjectManager *) stack->stream->odm, stack);

				while (gf_list_count(stack->seg)) gf_list_rem(stack->seg, 0);
				gf_odm_init_segments((GF_ObjectManager *) stack->stream->odm, stack->seg, &stack->control->url);

				stack->current_seg = 0;
				//do not restart if no mediaStartTime and speed is 1
				if ((stack->control->mediaStartTime>0) || gf_list_count(stack->seg) || (stack->control->mediaSpeed != FIX_ONE) ) {
					shall_restart = need_restart = 1;
				} else {
					shall_restart = need_restart = 0;
					//URL changed, we are by default in PLAY mode.
					stack->media_speed = 1;
				}

				stack->ck = gf_odm_get_media_clock(stack->stream->odm);
			}
			/*control has been removed and we were paused, resume*/
			else if (stack->paused) {
				mediacontrol_resume((GF_ObjectManager *) prev->odm, 0);
				stack->paused = 0;
			}
			/*MediaControl has been detached*/
			else {
				if (prev)
					gf_odm_remove_mediacontrol(prev->odm, stack);
				return;
			}
		}
	} else {
		stack->stream = gf_scene_get_media_object(stack->parent, &stack->control->url, GF_MEDIA_OBJECT_UNDEF, 0);
		if (!stack->stream || !stack->stream->odm) {
			if (stack->control->url.count) gf_term_invalidate_compositor(stack->parent->root_od->term);
			stack->stream = NULL;
			stack->changed = 0;
			return;
		}
		stack->ck = gf_odm_get_media_clock(stack->stream->odm);
		/*OD not ready yet*/
		if (!stack->ck) {
			stack->stream = NULL;
			if (stack->control->url.count) {
				stack->is_init = 0;
				gf_term_invalidate_compositor(stack->parent->root_od->term);
			}
			return;
		}
		gf_sg_vrml_field_copy(&stack->url, &stack->control->url, GF_SG_VRML_MFURL);
		gf_odm_set_mediacontrol((GF_ObjectManager *) stack->stream->odm, stack);

		while (gf_list_count(stack->seg)) gf_list_rem(stack->seg, 0);
		gf_odm_init_segments((GF_ObjectManager *) stack->stream->odm, stack->seg, &stack->control->url);
		stack->current_seg = 0;

		/*we shouldn't have to restart unless start/stop times have been changed, which is tested below*/
		need_restart = 0;
	}

	if (!stack->changed || !stack->control->enabled || !stack->stream) return;


	/*if not previously enabled and now enabled, switch all other controls off and reactivate*/
	if (!stack->enabled) {
		stack->enabled = 1;
		need_restart = gf_odm_switch_mediacontrol(stack->stream->odm, stack);
	}

	stack->changed = 0;

	if (!stack->control->mediaSpeed) shall_restart = 0;

	odm = (GF_ObjectManager *)stack->stream->odm;

	/*check for changes*/
	if (!stack->is_init) {
		/*not linked yet*/
		if (!odm) return;
		stack->media_speed = stack->control->mediaSpeed;
		stack->enabled = stack->control->enabled;
		stack->media_start = stack->control->mediaStartTime;
		stack->media_stop = stack->control->mediaStopTime;
		stack->is_init = 1;
		stack->paused = 0;
		/*the object has already been started, and media start time is not 0, restart*/
		if (stack->stream->num_open) {
			if ( (stack->media_start > 0) || (gf_list_count(stack->seg)>0 )  || (stack->media_speed!=FIX_ONE ) ) {
				mediacontrol_restart(odm);
			} else if (stack->media_speed == 0) {
				mediacontrol_pause(odm);
				stack->paused = 1;
			}
		}
		return;
	}

	if (stack->media_speed != stack->control->mediaSpeed) {
		/*if no speed pause*/
		if (!stack->control->mediaSpeed && !stack->paused) {
			mediacontrol_pause(odm);
			stack->paused = 1;
		}
		/*else resume if paused*/
		else if (stack->control->mediaSpeed && stack->paused) {
			mediacontrol_resume(odm, 0);
			stack->paused = 0;
			need_restart += shall_restart;
		}
		/*else set speed*/
		else if (stack->media_speed && stack->control->mediaSpeed) {
			/*don't set speed if we have to restart the media ...*/
			if (!shall_restart) MC_SetSpeed(odm, stack->control->mediaSpeed);
			need_restart += shall_restart;
		}
		/*init state was paused*/
		else if (!stack->media_speed) {
			need_restart ++;
		}
		stack->media_speed = stack->control->mediaSpeed;
	}
	/*check start/stop changes*/
	if (stack->media_start != stack->control->mediaStartTime) {
		stack->media_start = stack->control->mediaStartTime;
		need_restart += shall_restart;
	}
	/*stop change triggers restart no matter what (new range) if playing*/
	if (stack->media_stop != stack->control->mediaStopTime) {
		stack->media_stop = stack->control->mediaStopTime;
		if (stack->control->mediaSpeed) need_restart = 1;
	}

	if (need_restart) {
		mediacontrol_restart(odm);
	}

	/*handle preroll*/

}