//----------------------------------------------------------------------------------------------------------------------

        internal void ResetPlayableFrames()
        {
            DestroyPlayableFrames();

            //Recalculate the number of frames and create the marker's ground truth data
            int numFrames = TimelineUtility.CalculateNumFrames(m_clipOwner);

            m_playableFrames = new List <SISPlayableFrame>(numFrames);
            UpdatePlayableFramesSize(numFrames);
        }
//----------------------------------------------------------------------------------------------------------------------

        //Resize PlayableFrames and used the previous values
        internal void RefreshPlayableFrames()
        {
            //Clip doesn't have parent. Might be because the clip is being moved
            if (null == m_clipOwner.parentTrack)
            {
                return;
            }

            int numIdealNumPlayableFrames = TimelineUtility.CalculateNumFrames(m_clipOwner);

            //Change the size of m_playableFrames and reinitialize if necessary
            int prevNumPlayableFrames = m_playableFrames.Count;

            if (numIdealNumPlayableFrames != prevNumPlayableFrames)
            {
                //Change the size of m_playableFrames and reinitialize if necessary
                List <bool> prevUsedFrames = new List <bool>(prevNumPlayableFrames);
                foreach (SISPlayableFrame frame in m_playableFrames)
                {
                    prevUsedFrames.Add(null == frame || frame.IsUsed()); //if frame ==null, just regard as used.
                }

                UpdatePlayableFramesSize(numIdealNumPlayableFrames);

                //Reinitialize
                if (prevNumPlayableFrames > 0)
                {
                    for (int i = 0; i < numIdealNumPlayableFrames; ++i)
                    {
                        int prevIndex = (int)(((float)(i) / numIdealNumPlayableFrames) * prevNumPlayableFrames);
                        m_playableFrames[i].SetUsed(prevUsedFrames[prevIndex]);
                    }
                }
            }

            //Refresh all markers
            double timePerFrame      = TimelineUtility.CalculateTimePerFrame(m_clipOwner);
            int    numPlayableFrames = m_playableFrames.Count;

            for (int i = 0; i < numPlayableFrames; ++i)
            {
                m_playableFrames[i].SetIndexAndLocalTime(i, i * timePerFrame);
                m_playableFrames[i].Refresh(m_frameMarkersVisibility);
            }
        }
//----------------------------------------------------------------------------------------------------------------------

        private void UpdatePlayableFramesSize(int reqPlayableFramesSize)
        {
            Assert.IsNotNull(m_clipOwner);

            double timePerFrame = TimelineUtility.CalculateTimePerFrame(m_clipOwner);

            //Resize m_playableFrames
            if (m_playableFrames.Count < reqPlayableFramesSize)
            {
                int numNewPlayableFrames = (reqPlayableFramesSize - m_playableFrames.Count);
                List <SISPlayableFrame> newPlayableFrames = new List <SISPlayableFrame>(numNewPlayableFrames);
                for (int i = m_playableFrames.Count; i < reqPlayableFramesSize; ++i)
                {
                    newPlayableFrames.Add(CreatePlayableFrame(this, i, timePerFrame));
                }
                m_playableFrames.AddRange(newPlayableFrames);
            }

            if (m_playableFrames.Count > reqPlayableFramesSize)
            {
                int numLastPlayableFrames = m_playableFrames.Count;
                for (int i = reqPlayableFramesSize; i < numLastPlayableFrames; ++i)
                {
                    SISPlayableFrame curFrame = m_playableFrames[i];
                    curFrame?.Destroy();
                }
                m_playableFrames.RemoveRange(reqPlayableFramesSize, numLastPlayableFrames - reqPlayableFramesSize);
            }

            Assert.IsTrue(m_playableFrames.Count == reqPlayableFramesSize);

            for (int i = 0; i < reqPlayableFramesSize; ++i)
            {
                SISPlayableFrame curPlayableFrame = m_playableFrames[i];
                Assert.IsNotNull(curPlayableFrame);
                m_playableFrames[i].SetIndexAndLocalTime(i, timePerFrame * i);
            }
        }