📄 abstractcontroller.java
字号:
//////////////////////////////////////////////////////////// // // State methods // //////////////////////////////////////////////////////////// /** * Get the previous state of this Controller. */ public int getPreviousState() { return previousState; } /** * Set the current state of this Controller. This will * implicitly set the previous state as well. */ protected synchronized void setState(int state) { if(state == currentState) return; previousState = currentState; currentState = state; } /** * Get the current state of this Controller. */ public int getState() { return currentState; } /** * Set the targetState state of this Controller. */ protected void setTargetState(int state) { targetState = state; } /** * Get the target state of this Controller. */ public int getTargetState() { return targetState; } //////////////////////////////////////////////////////////// // // AbstractController methods // //////////////////////////////////////////////////////////// /** * Indicates to the framework that the end of media has been * reached. Marks the media time, sets the current and target * states to Prefetched, and posts an EndOfMediaEvent. * * @exception ClockStoppedException * If the AbstractController is not in the Started * state. */ protected synchronized void endOfMedia() throws ClockStoppedException { // Enforce state prereq if( currentState != Started ) { throw new ClockStoppedException(); } // Stop the Clock super.stop(); // Set the state and post an EndOfMediaEvent setState(Prefetched); setTargetState(Prefetched); postEndOfMediaEvent(); } //////////////////////////////////////////////////////////// // // Event methods // //////////////////////////////////////////////////////////// /** * Post a ControllerEvent to the Media Event Queue * * @param event * The ControllerEvent to post. */ protected void postEvent(ControllerEvent event) { eventqueue.postEvent(event); } /** * Post a TransitionEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * and Target State properties of the TransitionEvent. */ protected void postTransitionEvent() { postEvent( new TransitionEvent( this, previousState, currentState, targetState) ); } /** * Post a RealizeCompleteEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * and Target State properties of the RealizeCompleteEvent. */ protected void postRealizeCompleteEvent() { postEvent( new RealizeCompleteEvent( this, previousState, currentState, targetState) ); } /** * Post a PrefetchCompleteEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * and Target State properties of the PrefetchCompleteEvent. */ protected void postPrefetchCompleteEvent() { postEvent( new PrefetchCompleteEvent( this, previousState, currentState, targetState) ); } /** * Post a DeallocateEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * DeallocateEvent. */ protected void postDeallocateEvent() { postEvent( new DeallocateEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a StopEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * StopEvent. */ protected void postStopEvent() { postEvent( new StopEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a StopAtTimeEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * StopAtTimeEvent. */ protected void postStopAtTimeEvent() { postEvent( new StopAtTimeEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a StartEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, Media Time, and Time-base Time properties of * the StartEvent. */ protected void postStartEvent() { postEvent( new StartEvent( this, previousState, currentState, targetState, getMediaStartTime(), getTimeBaseStartTime()) ); } /** * Post a DataStarvedEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * DataStarvedEvent. */ protected void postDataStarvedEvent() { postEvent( new DataStarvedEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a EndOfMediaEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * EndOfMediaEvent. */ protected void postEndOfMediaEvent() { postEvent( new EndOfMediaEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a RestartingEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * RestartingEvent. */ protected void postRestartingEvent() { postEvent( new RestartingEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a StopByRequestEvent to the Media Event Queue. * Automatically fill in the Previous State, Current State, * Target State, and Media Time properties of the * StopByRequestEvent. */ protected void postStopByRequestEvent() { postEvent( new StopByRequestEvent( this, previousState, currentState, targetState, getMediaTime()) ); } /** * Post a ControllerClosedEvent to the Media Event Queue. */ protected void postControllerClosedEvent() { postEvent( new ControllerClosedEvent(this) ); } /** * Post a ControllerClosedEvent to the Media Event Queue. */ protected void postControllerErrorEvent(String msg) { postEvent( new ControllerErrorEvent(this, msg) ); } //////////////////////////////////////////////////////////// // // Synchronous state-changing methods // // These routines are called by way of a TransitionThread. // When these methods are called, the following assumptions // can be made: // // 1. The current state is less than the desired state. If // doSyncStart() is called, the Controller is guaranteed // to be in the Prefetched state. // // 2. The target state is greater than or equal to the // desired state. // // 3. Any state-related exceptions have been thrown already. // // 4. There are no other state-changing threads running. // //////////////////////////////////////////////////////////// /** * Gets the ThreadQueue object for this AbstractController. */ protected ThreadQueue getThreadQueue() { return threadqueue; } /** * Realize the AbstractController synchronously. * <p> * This method should not be called directly. Instead, call * realize(). * <p> * Synchronous method -- return when transition complete */ protected void synchronousRealize() { // Set the current state and post event setState( Realizing ); postTransitionEvent(); // Do the actual realizing if( doRealize() ) { // The realize was successful // Set the current state and post event setState( Realized ); postRealizeCompleteEvent(); // Set the initial rate setRate(1); // Set the initial media time setMediaTime( new Time(0) ); } else { // The realize was unsuccessful // Rely on the Controller to post the // ControllerErrorEvent // Reset the current and target states setState( Unrealized ); setTargetState( Unrealized ); } } /** * Realize the AbstractController synchronously. * <p> * This method should not be called directly. Instead, call * prefetch(). * <p> * Synchronous method -- return when transition complete */ protected void synchronousPrefetch() { // Does the controller need to be realized? if( currentState < Realized ) { synchronousRealize(); if (currentState < Realized) // realized failed - do not proceed. return; } // Set the current state and post event setState( Prefetching ); postTransitionEvent(); // Do the actual prefetching if( doPrefetch() ) { // The prefetch was successful // Set the current state and post event setState( Prefetched ); postPrefetchCompleteEvent(); // Set the initial media time setMediaTime( new Time(0) ); } else { // The prefetch was unsuccessful. // Rely on the Controller to post the // ControllerErrorEvent // Reset the current and target states setState( Realized ); setTargetState( Realized ); } } /** * Returns LATENCY_UNKNOWN. This method should be * overridden to report a more precise start latency. */ public Time getStartLatency() { if(currentState == Unrealized || currentState == Realizing) { throw new NotRealizedError( "Cannot get start latency from an unrealized Controller."); } return LATENCY_UNKNOWN; } /** * SyncStart the AbstractController synchronously at the * previously-specified time-base start time. * <p> * This method should not be called directly. Instead, call * syncStart(). * <p> * Synchronous method -- return when transition complete */ protected void synchronousSyncStart(Time t) { // Set the state and post event setState( Started ); postStartEvent(); // Calculate start latency. If unknown, asssume zero. Time latencyTime = getStartLatency(); long latency; if( latencyTime == LATENCY_UNKNOWN ) { latency = 0; } else { latency = latencyTime.getNanoseconds(); } long start = t.getNanoseconds(); long now = getTimeBase().getNanoseconds(); // If the start time is in the past, change it to now if(now + latency > start) t = new Time(now + latency); // Start the clock super.syncStart(t); // Do the actual syncStarting if(! doSyncStart(t) ) { // The syncStart was unsuccessful // Rely on the Controller to post the // ControllerErrorEvent // Reset the states setState( Prefetched ); setTargetState( Prefetched ); } } /** * For a given time-base start time, block until the * AbstractController should be started. For a given time- * base start time (t), this method will get the * AbstractController's start latency (l) and block until (t * - l). This method is useful for implementations of * doSyncStart(). * <p> * If the time-base time (t - l) has already passed, return * immediately. */ public void blockUntilStart(Time t) { // Calculate start latency. If unknown, asssume zero. Time latencyTime = getStartLatency(); long latency; if( latencyTime == LATENCY_UNKNOWN ) { latency = 0; } else { latency = latencyTime.getNanoseconds(); } long start = t.getNanoseconds(); long now = getTimeBase().getNanoseconds(); long delay = (start - latency - now)/1000000; // Wait for the syncTime if( delay > 0 ) { try { Thread.sleep(delay); } catch(InterruptedException e) {} } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -