using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace CHTest
{
    

    public partial class MAIN_FORM : Form
    {
        public  struct VideoRes
        {
            public int width;  // w
            public int height;  // h
            public int fps;
        };
        public struct VideoChannel
        {
            public VideoRes[] m_VideoRes;
            public int m_VideoIndex;
	        public int m_AudioIndex;
	        public int m_VideoResIndex;
            public String m_VideoName;
            public String m_AudioName; 
            public int m_Max_ResSize;
	        public int m_Slider_BR;
	        public int m_Slider_CO;
	        public int m_Slider_SA;
	        public int m_Slider_HU;
	        public int m_Slider_SH;

        };
        public MAIN_FORM()
        {
            int i;
            InitializeComponent();
            MAX_VIDEO_CHANNEL = 64;
            MAX_AUDIO_BUFSIZE = 1024 * 8 * 2;
            m_InitDone = 0;
            m_SupportGray = 0;
            m_hVideoDSP = new int[MAX_VIDEO_CHANNEL];
            m_hAudioDSP = new int[MAX_VIDEO_CHANNEL];
            video_curr_fps = new int[MAX_VIDEO_CHANNEL];
            m_VideoChannel = new VideoChannel[MAX_VIDEO_CHANNEL];
            m_WndHandle = new IntPtr[MAX_VIDEO_CHANNEL];
            m_VideorRect = new RECT[MAX_VIDEO_CHANNEL];
            m_Max_Video_Channels = 0;
            m_Max_Audio_Channels = 0;
            m_syncContext = new SynchronizationContext[MAX_VIDEO_CHANNEL];
            m_curr_ch = 0;
            for (i = 0; i < MAX_VIDEO_CHANNEL; i++)
            {
                m_hVideoDSP[i] = -1;
                m_hAudioDSP[i] = -1;
                m_VideoChannel[i].m_VideoRes = new VideoRes[MAX_VIDEO_CHANNEL];
                m_VideoChannel[i].m_AudioIndex = i;
                m_VideoChannel[i].m_VideoIndex = i;
                m_VideoChannel[i].m_Max_ResSize = 0;
                m_VideoChannel[i].m_VideoResIndex = 0;
                video_curr_fps[i] = 0;
                m_syncContext[i] = SynchronizationContext.Current; 
            }
        }
        DvrshMethod.RAWSTREAM_DIRECT_CALLBACK imageCallback;
        DvrshMethod.VIDEOSTATUS_CALLBACK m_VideoStatusCallback;
        DvrshMethod.RAWAUDIO_DIRECT_CALLBACK m_AudioCallback;
        public int MAX_VIDEO_CHANNEL;
        public int MAX_AUDIO_BUFSIZE;
        public int m_curr_ch;
        public Bitmap ch1_bitmap;
        public IntPtr ch1_rgbdata;
        public Bitmap ch2_bitmap;
        public IntPtr ch2_rgbdata;
        public int[] video_curr_fps;
        public int m_Max_Video_Channels;
        public int m_Max_Audio_Channels;
        public int m_InitDone;
        public int[] m_hVideoDSP;
        public int[] m_hAudioDSP;
        public int m_SupportGray;
        public IntPtr[] m_WndHandle;
        public RECT[] m_VideorRect;
        public int[] m_VideoUpateBusy;
        public VideoChannel[] m_VideoChannel;
        public SynchronizationContext[] m_syncContext; 
        private void OpenDevice_Click(object sender, EventArgs e)
        {
              this.InitVideoSys();
              this.GetVideoDeviceInfo();
             {
                SHOW_V1.Enabled = true;
                SHOW_V2.Enabled = true;
                SHOW_V3.Enabled = true;
                SHOW_V4.Enabled = true;
                OpenDevice.Enabled = false;
                CloseDvrs.Enabled = true;
                try
                {
                    //IntPtr Winhandle = new IntPtr();
                    imageCallback = new DvrshMethod.RAWSTREAM_DIRECT_CALLBACK(CallbackFun);
                    m_VideoStatusCallback = new DvrshMethod.VIDEOSTATUS_CALLBACK(VideoStatusCallbackFun);
                    m_AudioCallback = new DvrshMethod.RAWAUDIO_DIRECT_CALLBACK(AudioCallbackFun);
                   
                    ch2_bitmap = null;
                    ch1_bitmap = null;
                     //DvrshMethod.RegisterRAWDirectCallback(0,imageCallback, this.Handle);
                     //DvrshMethod.RegisterVideoStatusCallback(1,m_VideoStatusCallback, this.Handle);
                    //DvrshMethod.OutputDebugString("RegisterStreamDirectReadCallback");
                    sys_timer.Enabled = true;
                    sys_timer.Interval = 1000;//定时器时间间隔
                    sys_timer.Start();   //定时器开始工作
                    m_curr_ch = 0;
                    m_WndHandle[0] = V_CH1.Handle;
                    m_WndHandle[1] = V_CH2.Handle;
                    m_WndHandle[2] = V_CH3.Handle;
                    m_WndHandle[3] = V_CH4.Handle;

                    m_VideorRect[0].left = V_CH1.Left;
                    m_VideorRect[0].right = V_CH1.Right;
                    m_VideorRect[0].top = V_CH1.Top;
                    m_VideorRect[0].bottom = V_CH1.Bottom;

                    m_VideorRect[1].left = V_CH2.Left;
                    m_VideorRect[1].right = V_CH2.Right;
                    m_VideorRect[1].top = V_CH2.Top;
                    m_VideorRect[1].bottom = V_CH2.Bottom;

                    m_VideorRect[2].left = V_CH3.Left;
                    m_VideorRect[2].right = V_CH3.Right;
                    m_VideorRect[2].top = V_CH3.Top;
                    m_VideorRect[2].bottom = V_CH3.Bottom;

                    m_VideorRect[3].left = V_CH4.Left;
                    m_VideorRect[3].right = V_CH4.Right;
                    m_VideorRect[3].top = V_CH4.Top;
                    m_VideorRect[3].bottom = V_CH4.Bottom;



                }
                catch (Exception ex)
                {


                }
             }
             UpdateForm();
        }
        public void GetVideoDeviceInfo()
        {
	        int i;
            DvrshMethod.GetCurrSystemDevice();
	            //-------------
            m_Max_Video_Channels = DvrshMethod.GetVideoTotalChannels();
            m_Max_Audio_Channels = DvrshMethod.GetAudioTotalChannels();
	            for( i = 0;i<m_Max_Video_Channels;i++)
	            {
                    m_VideoChannel[i].m_Max_ResSize = DvrshMethod.GetVideoMaxResIndex(i);
                    Byte[] bPara = new Byte[256];
                    DvrshMethod.GetVideoNameByIndex(i, ref bPara[0]);
                    m_VideoChannel[i].m_VideoName = System.Text.Encoding.Default.GetString(bPara).TrimEnd('\0');
                    if (m_VideoChannel[i].m_Max_ResSize > 0)
		            {
                        for (int k = 0; k < m_VideoChannel[i].m_Max_ResSize; k++)
			            {
                            m_VideoChannel[i].m_VideoRes[k].width = DvrshMethod.GetVideoMaxResWidthByIndex(i, k);
                            m_VideoChannel[i].m_VideoRes[k].height = DvrshMethod.GetVideoMaxResHeightByIndex(i, k);
                            m_VideoChannel[i].m_VideoRes[k].fps = DvrshMethod.GetVideoMaxResFpsByIndex(i, k);
                            Debug.WriteLine("CH[" + i.ToString() + "] index="+k.ToString() + ":w=" + m_VideoChannel[i].m_VideoRes[k].width.ToString() + "h=" + m_VideoChannel[i].m_VideoRes[k].height + "(" + m_VideoChannel[i].m_VideoRes[k].fps.ToString()+ ")");
			            }
		}
		
	}
	for( i = 0;i<m_Max_Audio_Channels;i++)
	{
        Byte[] bPara = new Byte[256];
        DvrshMethod.GetAudioNameByIndex(i, ref bPara[0]);
        m_VideoChannel[i].m_AudioName = System.Text.Encoding.Default.GetString(bPara).TrimEnd('\0');
	}
	
}
        public void VideoStatusCallbackFun(int channelNumber, int bStatus, IntPtr context)
        {
            /*
            if (channelNumber ==0)
            {
                if (bStatus == 0)
                {
                    status_ch1.Text = "Video Lost";
                }
                else
                {
                    status_ch1.Text = "Video In";
                }
            
            }
            if (channelNumber == 1)
            {
                if (bStatus == 0)
                {
                    status_ch2.Text = "Video Lost";
                }
                else
                {
                    status_ch2.Text = "Video In";
                }

            }
             * */
        }
        public void AudioCallbackFun(int channelNumber, IntPtr DataBuf, int FrameType, int size, IntPtr context)
        {
        }
        public  void CallbackFun(int channelNumber, IntPtr DataBuf, int FrameType, int width, int height, IntPtr context)
        {
            //Debug.WriteLine("输出调试信息2");
            //DvrshMethod.OutputDebugString("CH-" + channelNumber.ToString() + " " + width.ToString() + "X" + height.ToString()+"\n");
              video_curr_fps[channelNumber]++;
/*
            if (channelNumber == 0)
            {
          
                if (ch1_bitmap == null)
                {
                    //ch1_bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                    if (m_SupportGray == 0)
                    {
                        ch1_bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                    }
                    else
                    {
                        ch1_bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                    }
                    //Format24bppRgb
                    bit_ch1.Image = ch1_bitmap;
                    //ch1_rgbdata = Marshal.AllocHGlobal(width * height * 3);
                }
                
                ch1_rgbdata = Marshal.AllocHGlobal(width * height * 3);
                DvrshMethod.ChangeYUVToRGB(DataBuf, ch1_rgbdata, width, height);
                //UpdateBitmap(0,ch1_bitmap, ch1_rgbdata, width, height);
                //m_syncContext[0].Post(SetVideoImg, ch1_bitmap);
                //bit_ch1.Image = ch1_bitmap;  //need add some other Invoke
                ch1_total_fps++;
                Marshal.FreeHGlobal(ch1_rgbdata);
            }
            else if (channelNumber == 1)
            {

                if (ch2_bitmap == null)
                {
                    if (m_SupportGray == 0)
                    {
                        ch2_bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                    }
                    else
                    {
                        ch2_bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                    }
                    bit_ch2.Image = ch2_bitmap;
                    //ch2_rgbdata = Marshal.AllocHGlobal(width * height * 3);
                }
                
                ch2_rgbdata = Marshal.AllocHGlobal(width * height * 3);
                
                DvrshMethod.ChangeYUVToRGB(DataBuf, ch2_rgbdata, width, height);
                //UpdateBitmap(1,ch2_bitmap, ch2_rgbdata, width, height);
                //bit_ch2.Image = ch2_bitmap; //need add some other Invoke
                ch2_total_fps++;
                Marshal.FreeHGlobal(ch2_rgbdata);
            }
           */
        }
        private void SetVideoImg(object img)
        {
            bit_ch1.Image =(Bitmap)img;
        }
        public  void  UpdateBitmap(int Channels, Bitmap bitmap,IntPtr rgbImageData, int originalWidth, int originalHeight)
        {
           
            BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptrbmp = bmpData.Scan0;
            if (m_SupportGray == 0)
            {
                DvrshMethod.CopyMemory(ptrbmp, rgbImageData, (uint)(originalWidth * originalHeight * 3));
            }
            else
            {
                DvrshMethod.CopyMemory(ptrbmp, rgbImageData, (uint)(originalWidth * originalHeight * 1));
            }
            bitmap.UnlockBits(bmpData);
         
            
        }
        private void CloseAudio(int Channels)
        {

            if (m_hAudioDSP[Channels] != -1)
            {
                DvrshMethod.StopAudioCapture(m_hAudioDSP[Channels]);
                m_hAudioDSP[Channels] = -1;
            }
        }
        private int OpenAudio(int Channels)
        {
            int m_audioIndex;
            m_audioIndex = m_VideoChannel[Channels].m_AudioIndex;
            //m_audioIndex = m_audioIndex - 1;
            if ((m_audioIndex >= 0) && (m_audioIndex < m_Max_Audio_Channels))
            {

                CloseAudio(Channels);
                m_hAudioDSP[Channels] = DvrshMethod.AudioChannelOpen(Channels, m_audioIndex, MAX_AUDIO_BUFSIZE);
                DvrshMethod.RegisterAudioDirectCallback(Channels, m_AudioCallback, this.Handle);
                DvrshMethod.AudioOutOpen(Channels, this.Handle);
                DvrshMethod.AudioOutPlay(Channels);
                return 1;
            }
            else
            {
                return 0;
            }
        }
        private void CloseVideo(int Channels)
        {

            if (m_hVideoDSP[Channels] != -1)
            {
                DvrshMethod.StopVideoCapture(m_hVideoDSP[Channels]);
                m_hVideoDSP[Channels] = -1;
            }
        }
        private void OpenVideo(int Channels)
        {
            int m_videoIndex;
            int m_videoResIndex;
            m_videoIndex = m_VideoChannel[Channels].m_VideoIndex;
            m_videoResIndex = m_VideoChannel[Channels].m_VideoResIndex;
            //m_videoIndex = m_videoIndex - 1;
            if ((m_videoIndex >= 0) && (m_videoIndex < m_Max_Video_Channels))
            {

                CloseVideo(Channels);
                m_hVideoDSP[Channels] = DvrshMethod.VideoChannelOpen(Channels,m_videoIndex,m_VideoChannel[Channels].m_VideoRes[m_videoResIndex].width, m_VideoChannel[Channels].m_VideoRes[m_videoResIndex].height, m_VideoChannel[Channels].m_VideoRes[m_videoResIndex].fps); 
                if (m_hVideoDSP[Channels] != -1)
                {
                    DvrshMethod.RegisterRAWDirectCallback(Channels, imageCallback, this.Handle);
                    DvrshMethod.RegisterVideoStatusCallback(Channels, m_VideoStatusCallback, this.Handle);
                    DvrshMethod.StartVideoPreview(m_hVideoDSP[Channels], m_WndHandle[Channels], ref m_VideorRect[Channels]);
                }
            }
        }
        private void SHOW_V1_Click(object sender, EventArgs e)
        {
         
            int ch;
            ch = 0;
            OpenVideo(ch);
            //OpenAudio(ch);
            UpdateForm();
        }

        private void SHOW_V2_Click(object sender, EventArgs e)
        {

            int ch;
            ch = 1;
            OpenVideo(ch);
            //OpenAudio(ch);
            UpdateForm();
        }
        private void SHOW_V3_Click(object sender, EventArgs e)
        {
            int ch;
            ch = 2;
            OpenVideo(ch);
            //OpenAudio(ch);
            UpdateForm();
        }

        private void SHOW_V4_Click(object sender, EventArgs e)
        {
            int ch;
            ch = 3;
            OpenVideo(ch);
            //OpenAudio(ch);
            UpdateForm();
        }
        public void InitVideoSys()
        {
            int i;
            if (m_InitDone == 1)
            {
                this.ExitVideoSys();
            }
            DvrshMethod.SetMax_VideoSize(1920, 1200); // 
            DvrshMethod.InitHwDSPs();
            m_Max_Video_Channels = DvrshMethod.GetVideoTotalChannels();
            for (i = 0; i < m_Max_Video_Channels; i++)
            {
                m_VideoChannel[i].m_Max_ResSize = DvrshMethod.GetVideoMaxResIndex(i);
                if (m_VideoChannel[i].m_Max_ResSize > 0)
                {
                    for (int k = 0; k < m_VideoChannel[i].m_Max_ResSize; k++)
                    {
                        m_VideoChannel[i].m_VideoRes[k].width = DvrshMethod.GetVideoMaxResWidthByIndex(i, k);
                        m_VideoChannel[i].m_VideoRes[k].height = DvrshMethod.GetVideoMaxResHeightByIndex(i, k);
                        m_VideoChannel[i].m_VideoRes[k].fps = DvrshMethod.GetVideoMaxResFpsByIndex(i, k);

                    }
                }
            }
            m_InitDone = 1;
        }
        public void ExitVideoSys()
        {
            if (m_InitDone == 0) return;
            for (int i = 0; i < MAX_VIDEO_CHANNEL; i++)
            {
                 CloseVideo(i);
                 CloseAudio(i);
            }
            DvrshMethod.DeInitHwDSPs();
            m_InitDone = 0;
        }
        private void CloseDvrs_Click(object sender, EventArgs e)
        {
            this.ExitVideoSys();
            if (ch1_bitmap != null)
            {
                //Marshal.FreeHGlobal(ch1_rgbdata);
            
            }
            if (ch2_bitmap != null)
            {
                //Marshal.FreeHGlobal(ch2_rgbdata);

            }
            OpenDevice.Enabled = true;
            SHOW_V1.Enabled = false;
            SHOW_V2.Enabled = false;
            SHOW_V3.Enabled = false;
            SHOW_V4.Enabled = false;
            CloseDvrs.Enabled = false;
            //System.Environment.Exit(0);
        }

        private void CAP_V1_Click(object sender, EventArgs e)
        {
             String  path ;
             path = "D:\\00" + DateTime.Now.ToString("yyyyMMddhhmmss") +".bmp";
             if (m_InitDone == 0) return;
             DvrshMethod.SaveCaptureImage(0, path);
        }

        private void CAP_V2_Click(object sender, EventArgs e)
        {
            String path;
            path = "D:\\00" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".bmp";
            if (m_InitDone == 0) return;
            DvrshMethod.SaveCaptureImage(1, path);
        }

        private void CAP_V3_Click(object sender, EventArgs e)
        {
            String path;
            path = "D:\\00" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".bmp";
            if (m_InitDone == 0) return;
            DvrshMethod.SaveCaptureImage(2, path);
        }

        private void CAP_V4_Click(object sender, EventArgs e)
        {
            String path;
            path = "D:\\00" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".bmp";
            if (m_InitDone == 0) return;
            DvrshMethod.SaveCaptureImage(3, path);
        }


        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.ExitVideoSys();
        }

        private void VSTART_V1_Click(object sender, EventArgs e)
        {
                    //DvrshMethod.SaveOneCaptureVideo(0, "D:\\");
                    //VSTART_V1.Enabled = false;
                    //VSTOP_V1.Enabled = true;
        }

        private void VSTOP_V1_Click(object sender, EventArgs e)
        {
               //DvrshMethod.StopOneCaptureVideo(0);
               //VSTART_V1.Enabled = true;
               //VSTOP_V1.Enabled = false;
        }

        private void VSTART_V2_Click(object sender, EventArgs e)
        {
                    //DvrshMethod.SaveOneCaptureVideo(1, "D:\\");
                    VSTART_V2.Enabled = false;
                    VSTOP_V2.Enabled = true;
        }

        private void VSTOP_V2_Click(object sender, EventArgs e)
        {
            //DvrshMethod.StopOneCaptureVideo(1);
            VSTART_V2.Enabled = true;
            VSTOP_V2.Enabled = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
           //RECT r;
           m_VideoChannel[m_curr_ch].m_VideoResIndex = Video_SIZE.SelectedIndex;
          
          //r.left = V_CH1.Left;
          //r.right = V_CH1.Right;
          //r.top = V_CH1.Top;
          //r.bottom = V_CH1.Bottom;

          CloseVideo(m_curr_ch);
          //CloseAudio(m_curr_ch);
          OpenVideo(m_curr_ch);
          //OpenAudio(m_curr_ch);
          UpdateForm();
        }

        private void SIZE_SET_Click(object sender, EventArgs e)
        {
             String str;
            str = CH_NAME.Text;
            //DvrshMethod.SetVideoCHName(0, CH_NAME.Text);
        }

        private void CH_SET_Click(object sender, EventArgs e)
        {
            DvrshMethod.OpenVideoColorSetting(m_curr_ch);
        }
        private void UpdateForm()
        {
            Video_SIZE.Items.Clear();
            Video_SIZE.Text = "";
            if (m_curr_ch >= m_Max_Video_Channels) return;
            for (int k = 0; k < m_VideoChannel[m_curr_ch].m_Max_ResSize; k++)
            {
                string w;
                string h;
                string fps;
                w = m_VideoChannel[m_curr_ch].m_VideoRes[k].width.ToString();
                h = m_VideoChannel[m_curr_ch].m_VideoRes[k].height.ToString();
                fps = m_VideoChannel[m_curr_ch].m_VideoRes[k].fps.ToString();
                Video_SIZE.Items.Add(w+"X"+h+"("+fps+")");
            }
            Video_SIZE.SelectedIndex = m_VideoChannel[m_curr_ch].m_VideoResIndex;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //Video_SIZE.Items.Add("960H");
            //Video_SIZE.Items.Add("720P");
            //Video_SIZE.Items.Add("1080P");

            BR.Text = "136";
            CO.Text = "146 ";
            SA.Text = "136 ";
            HU.Text = "0";
            UpdateForm();
        }

        private void sys_timer_Tick(object sender, EventArgs e)
        {
            ch1_fps.Text = "CH1:" + video_curr_fps[0].ToString() + "FPS";
            video_curr_fps[0] = 0;
            ch2_fps.Text = "CH2:" + video_curr_fps[1].ToString() + "FPS";
            video_curr_fps[1] = 0;
            ch3_fps.Text = "CH3:" + video_curr_fps[2].ToString() + "FPS";
            video_curr_fps[2] = 0;
            ch4_fps.Text = "CH4:" + video_curr_fps[3].ToString() + "FPS";
            video_curr_fps[3] = 0;

        }

        private void UTC_UP_Click(object sender, EventArgs e)
        {
            //DvrshMethod.SetUTC_PELCO_UP(m_curr_ch);
        }

        private void UTC_LEFT_Click(object sender, EventArgs e)
        {
            //DvrshMethod.SetUTC_PELCO_LEFT(m_curr_ch);
        }

        private void UTC_SET_Click(object sender, EventArgs e)
        {
            //DvrshMethod.SetUTC_PELCO_SET(m_curr_ch);
        }

        private void UTC_RIGHT_Click(object sender, EventArgs e)
        {
            //DvrshMethod.SetUTC_PELCO_RIGHT(m_curr_ch);
        }

        private void UTC_DWON_Click(object sender, EventArgs e)
        {
            //DvrshMethod.SetUTC_PELCO_DOWN(m_curr_ch);
        }

        private void CH_SET_COLOR_Click(object sender, EventArgs e)
        {
            int Brightness;
            int Contrast;
            int Saturation;
            int Hue;
            Brightness = int.Parse(BR.Text);  // 0x08;
            Contrast = int.Parse(CO.Text); ;
            Saturation = int.Parse(SA.Text); ;
            Hue = int.Parse(HU.Text); ;
            DvrshMethod.SetVideoPara(m_curr_ch, Brightness, Contrast, Saturation, Hue);
        }

        private void V_CH1_Click(object sender, EventArgs e)
        {
            m_curr_ch = 0;
            UpdateForm();
        }

        private void V_CH2_Click(object sender, EventArgs e)
        {
            m_curr_ch = 1;
            UpdateForm();
        }
       

        private void V_CH3_Click(object sender, EventArgs e)
        {
            m_curr_ch = 2;
            UpdateForm();
        }

        private void V_CH4_Click(object sender, EventArgs e)
        {
            m_curr_ch = 3;
            UpdateForm();
        }
    }
}
