XDL Manual

XDL VideoView 활용 세번째

(piXoneer XDL Tutorial)

 

 

 

 

 

 

이 문서는 XDL Development Library

 설치 및 사용하기 위한 문서입니다.

 

2017. 01.

 

 

목차

XDL VideoView 활용 세번째... 1

1    사용하기... 1

1.1    Play 시간 컨트롤 넣기... 1

1.2    TrackBar 동기화... 1

 

 

 

 

1     사용하기

본 튜터리얼을 공부하기 전에 먼저 XDL VideoView 활용 두번째를 먼저 선행하시기 바랍니다. XDL VideoView 활용 두번째에 이어서 진행합니다.

1.1    Play 시간 컨트롤 넣기

1.1.1     디자인창에서 labelTrackBar를 이용해 다음과 같이 디자인한다. label_CurrentTime, trackBar_PlayControl, label_TotalTime을 입력한다. UI 디자인에 대해서는 C# 매뉴얼을 참조한다.

 

1.2    TrackBar 동기화

1.2.1     디자인창에서 Toolbar[File]-[Open]을 더블클릭하여 함수를 자동 생성하고 두번째 매뉴얼을 기준으로 다음과 같이 기능을 추가한다. Timer를 추가하고 Frame정보를 위한 TotalFrameCurrentFrame을 설정한다.

 

enum VideoAction { STOP, PLAYING, PAUSED }

struct VideoState
{
    public XVideo video;                  // 파일이나 네트워크로부터 입력되는 스트리밍데이터를 제어하는 기능을 수행할 객체 선언
    public XVideoChannel videoChannel;    // 동영상 개체에 포함된 채널 객체 선언
    public string videoFilePath;          // 동영상 파일 경로 
public VideoAction action;		// 비디오 플레이 상태를 정의하는 객체 선언
public long currentFrame;              // 재생중인 동영상의 현재 프레임 위치
    public long totalFrame;                // 동영상 전체 프레임 수  

}

private XVideoIO m_videoIO = null;        // 동영상의 입출력을 담당할 객체 선언
private VideoState VS;			// 비디오 상태를 관리하는 객체 선언

private System.Threading.Timer m_timer;         // 재생 컨트롤 바 동작을 위한 타이머
private object m_lockCurFrame = new object();   // 재생 컨트롤 바와의 동기화를 위한 Lock 객체

 

1.2.2     Timer를 생성하고 TotalFrameCurrentFrame를 초기화 시킨다.

public Form1()
{
    InitializeComponent();
    m_videoIO = new XVideoIO(); // VideoIO를 생성
    
    VideoInit();
    nxVideoLayerOverlay1.LayerVisible = true;

// 재생 컨트롤 바 동작을 위한 타이머 생성
    m_timer = new System.Threading.Timer(timer_Tick);

    // 타이머 옵션 변경
    m_timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);

}

private void VideoInit()
{
    // VideoState의 초기화
    VS.video = null;   
    VS.videoChannel = null;    
    VS.videoFilePath = string.Empty;
VS.totalFrame = 0;
    VS.currentFrame = 0;
    VS.action = VideoAction.STOP;
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // 동영상 채널 정보 초기화
    nxVideoView1.ResetVideoChannel();

    if (VS.video != null)
    {
        // 동영상 객체 Close
        VS.video.Close();
        VS.video = null;
    }

    if (m_videoIO != null)
    {
        // 동영상 입출력 객체 Dispose
        m_videoIO.Dispose();
    }
}

 

1.2.3     OnOpen 함수에 TotalFrame을 얻어 VideoState에 저장한다..

public void OnOpen()
{
    try
    {
        string strError = null;
        // 동영상 스트림 정보 가져오기
        VS.video = m_videoIO.OpenFile(VS.videoFilePath, "XFFMPDRIVER", out strError);

        if (VS.video == null)
        {
            MessageBox.Show(this, "동영상 재생에 실패하였습니다. 파일을 확인해주십시오.", "파일 열기");
            return;
        }

        // 다중 채널을 가진 동영상 객체의 Channel 인덱스
        int nIdxChannel = 0;

        // 동영상 뷰에 재생할 동영상 채널을 성정
        nxVideoView1.SetVideoChannel(VS.video, nIdxChannel);

        // 입력 인덱스에 해당하는 Channel을 가져오기
        VS.videoChannel = VS.video.GetChannel(nIdxChannel);

        // GetChannel에 실패할 경우 Null 객체가 return되며, 그에 대한 예외처리
        if (VS.videoChannel == null)
        {
            MessageBox.Show(this, "동영상 재생에 실패하였습니다. 파일을 확인해주십시오.", "파일 열기");
            return;
        }

        // 동영상 객체에 포함된 Channel 객체 중 해당 Channel 객체를 활성화
        // 활성화된 객체만 스트리밍이 수행
        VS.videoChannel.Activate();

// 동영상의 Frame 정보를 얻어오기
        VS.totalFrame = VS.videoChannel.GetNumFramesVideo();

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        MessageBox.Show(this, "재생 실패!", "동영상");
        VS.action = VideoAction.STOP;
    }
}

 

1.2.4     OnStop 함수에 에 currentFrame을 초기화 시킨다.

public void OnStop()
{
    if (VS.videoChannel != null)
    {
        // 재생 Frame Buffer를 삭제
        VS.videoChannel.ClearFrameBuffer();
        // 동영상 재생 스크린을 갱신한다.
        nxVideoView1.RefreshScreen();
        // 동영상 재생 중지
        VS.videoChannel.Stop();
        VS.videoChannel = null;
    }

    // 동영상 채널 정보 초기화
    nxVideoView1.ResetVideoChannel();

    if (VS.video != null)
    {
        // 동영상 객체 Close
        VS.video.Close();
        VS.video = null;
    }

VS.currentFrame = 0;
    VS.action = VideoAction.STOP;
}

 

1.2.5     File-Open 버튼을 눌렀을 때 기능을 업데이트 시킨다.

private void toolStripMenuOpen_Click(object sender, EventArgs e)
{
// 새로운 파일 Open을 수행한다.
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "TS file(*.ts)|*.ts||";
    openFileDialog.RestoreDirectory = true;

    if (openFileDialog.ShowDialog() != DialogResult.OK) return;

    string videoPath = openFileDialog.FileName;

    // 동영상 파일의 존재 유무 체크
    if (System.IO.File.Exists(videoPath) == false)
    {
        MessageBox.Show(this, "해당 경로에 영상이 존재하지 않습니다.", "오류");
        return;
    }

// 파일 경로를 저장한다.
    VS.videoFilePath = videoPath;

    // 둥영상의 재생상태가 중지가 아닐 경우 동영상 재생 중지
    OnStop();

// 동영상 상태를 업데이트 시키기 위해 Timer를 작동 시킨다. 100msec간격으로 설정한다.
    OnTimer();

// Play되는 시간 정보를 도시하기 위해 Timer설정과 TrackBar와 Label을 초기화 한다. 
    InitTrackBarLabel();


    // 동영상 스트리밍 환경을 생성시킨다.
    OnOpen();

    // 동영상을 Play 시킨다.
    OnPlay();
}

 

 

1.2.6     Play, Pause, Stop버튼을 눌렀을 때 기능을 업데이트 시킨다.

private void button_Play_Click(object sender, EventArgs e)
{
    // 비디오가 Stop인 상태인 경우 다시 비디오를 저장된 파일 경로로부터 Open해서 설정한다. 
    if (VS.action == VideoAction.STOP)
    {
        // 동영상 상태를 업데이트 시키기 위해 Timer를 작동 시킨다. 
        OnTimer();

        // 동영상 스트리밍 환경을 생성시킨다.
        OnOpen();
    }

    // 설정된 비디오를 Play한다.
    OnPlay();
}

private void button_Pause_Click(object sender, EventArgs e)
{
    // Play되고 있는 비디오를 Pause시킨다.
    OnPause();
}

private void button_Stop_Click(object sender, EventArgs e)
{
    // Play가 종료되었으므로 Timer를 종료 시킨다.
    StopTimer();

    // Play를 중단한다.
    OnStop();

    // Play가 Stop되었으므로 TrackBar컨트롤과 Label을 초기화 시킨다.
    InitTrackBarLabel();
}

 

 

1.2.7     InitTrackBarLabel, OnTimer, StopTimer를 정의한다.

public void InitTrackBarLabel()
{
    // TrackBar를 설정하기 위해 컨트롤의 최대값을 설정한다. 
    trackBar_PlayControl.Maximum = unchecked((int)VS.totalFrame);

    // Total 시간에 대해 정보를 Label로 설정한다. 
    int nTotalSec = unchecked((int)(VS.totalFrame * (1.0 / 30)));
    TimeSpan getTotalTimeSpan = TimeSpan.FromSeconds(nTotalSec);
    string strTime = getTotalTimeSpan.ToString("hh':'mm':'ss");
    label_TotalTime.Text = strTime;
}

public void OnTimer()
{
    m_timer.Change(0, 100);
}

public void StopTimer()
{
    if (m_timer != null)
    {
        m_timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
    }
}

 

1.2.8     디자인창에서 Video Overlay Layer컨트롤을 클릭하고 [속성]-[이벤트]탭에서 OnOrthoRender행을 더블클릭하여 nxVideoLayerOverlay1_OnOrthoRender함수를 자동 생성하고 NXVideoDrawArgs 인자로 넘어오는 값으로부터 PTS값을 얻어 현재 Frame이 몇번째인지를 계산하여 currentFrame에 저장한다. 참고로 OnOrthoRender는 화면이 갱신될때마다 호출되는 Callback함수이다.

// PTS값을 얻기 위해 OnOrthoRender함수를 이용한다.
private bool nxVideoLayerOverlay1_OnOrthoRender(NXVideoLayer sender, NXVideoDrawArgs DrawArgs)
{
    try
    {
        lock (m_lockCurFrame)
        {
            // 현재 재생중인 화면의 PTS(Presentation TimeStamp) 값 얻어오기
            Int64 pts = DrawArgs.PTS;

            // PTS를 이용한 현재 재생중인 화면의 프레임 위치를 얻어오기
            VS.currentFrame = VS.videoChannel.PtsToFrameNumber(pts);
            if (VS.currentFrame >= VS.totalFrame) VS.currentFrame = VS.totalFrame;
            if (VS.currentFrame < 0) VS.currentFrame = 0;
        }
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex);	
    }
    return default(bool);
}

 

1.2.9     Timer함수를 통해 현재 도시되는 Frame이 어느정도 되는지와 각종 재생 상태를 업데이트 시키고 만약 Play가 종료시점에 도달하면 Stop을 수행한다.

private void timer_Tick(object state)
{
    lock (m_lockCurFrame)
    {
        if (VS.action != VideoAction.STOP)
        {
            // 현재 재생되고 있는 동영상의 시간을 계산
            int nSec = unchecked((int)(VS.currentFrame * (1.0 / 30)));
            int nTotalSec = unchecked((int)(VS.totalFrame * (1.0 / 30)));

            long nCheckFrame = VS.totalFrame - VS.currentFrame;

            if (nCheckFrame <= 30)
            {
                nSec = nTotalSec;
            }

            string strTime;

            TimeSpan getTimeSpan = TimeSpan.FromSeconds(nSec);
            strTime = getTimeSpan.ToString("hh':'mm':'ss");
            int nCurFrame = unchecked((int)VS.currentFrame);

            BeginInvoke(new Action(delegate
            {
                // 현재 재생되고 있는 동영상의 시간을 문자형태로 화면 도시
                label_CurrentTime.Text = strTime;

                // 현재 재생되고 있는 동영상의 시간을 Track 바 컨트롤에 도시
                trackBar_PlayControl.Value = nCurFrame;
                if (nSec == nTotalSec)
                {
                    // Play가 종료되었으므로 Timer를 종료 시킨다.
                    StopTimer();

                    // Play를 중단한다.
                    OnStop();

                    // Play가 Stop되었으므로 TrackBar컨트롤과 Label을 초기화 시킨다.
                    InitTrackBarLabel();
                }
            }));
        }
    }
}

 

1.2.10  [F5]키를 눌러 프로그램을 실행하여 stream.ts파일을 Open한다.