首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Windows平台RTMP直播推送集成简要说明

Windows平台RTMP直播推送集成简要说明

原创
作者头像
音视频牛哥
修改2021-04-01 14:14:40
修改2021-04-01 14:14:40
3K0
举报

好多开发者在集成大牛直播SDK (官方)的Windows平台RTMP推送模块时吓一跳,怎么这么多接口?本文做个简单的拆分:

初始化

初始化之前,如需设置日志路径,调用NTSmartLog.NT_SL_SetPath(log_path); 设置日志存放路径。

设置过后,调用NT_PB_Init()接口,完成SDK初始化动作,注意,哪怕多实例推送,Init()接口也仅需调一次,同理,UnInit()接口也是。

然后,代码会判断系统是不是支持WR模式采集窗口,WR这种只有Win10高版本的才支持,如果不需要用到采集窗口,这个接口可忽略。

代码语言:javascript
复制
        /*
		 * 检查是否支持WR方式采集窗口
         * is_supported: 输出参数, 输出1表示支持, 0表示不支持
         * 注意:这个需要win10较高版本才支持
         * 成功返回 NT_ERC_OK
		 */
        [DllImport(@"SmartPublisherSDK.dll")]
		public static extern UInt32 NT_PB_IsWRCaptureWindowSupported(ref Int32 is_supported);

再往下,是遍历系统支持的硬解、摄像头等信息,比如LoadHWVideoEncoderInfos():

代码语言:javascript
复制
        private void LoadHWVideoEncoderInfos()
        {            
	        hw_video_encoder_infos_.Clear();

	        Int32 count = 0;
            UInt32 ret = NTSmartPublisherSDK.NT_PB_GetHWVideoEncoderInfoCount(ref count);
	        
            if (NTBaseCodeDefine.NT_ERC_OK == ret && count > 0)
	        {
                IntPtr ptr_hw_video_encoder_infos = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NT_PB_HWVideoEncoderInfo)) * count);
                
                Int32 out_count = 0;

                ret = NTSmartPublisherSDK.NT_PB_GetHWVideoEncoderInfos(ptr_hw_video_encoder_infos, count, ref out_count);

                if (ret != NTBaseCodeDefine.NT_ERC_OK || out_count < 1)
                {
                    hw_video_encoder_infos_.Clear();
                }
                else
                {
                    for (int i = 0; i < out_count; i++)
                    {
                        NT_PB_HWVideoEncoderInfo hw_video_encoder_info = (NT_PB_HWVideoEncoderInfo)Marshal.PtrToStructure(ptr_hw_video_encoder_infos + i * Marshal.SizeOf(typeof(NT_PB_HWVideoEncoderInfo)), typeof(NT_PB_HWVideoEncoderInfo));
                        
                        hw_video_encoder_infos_.Add(hw_video_encoder_info);
                    }
                }

               Marshal.FreeHGlobal(ptr_hw_video_encoder_infos);
	        }
        }

代码语言:javascript
复制
            if (hw_video_encoder_infos_.Count > 0)
            {
                EnableHWVideoEncoderControls(true);
                FillVideoEncodersControl((uint)NTCommonMediaDefine.NT_MEDIA_CODEC_ID.NT_MEDIA_CODEC_ID_H264);
            }

紧接着是Audio和camera相关:

代码语言:javascript
复制
            int auido_devices = 0;

            if (NTBaseCodeDefine.NT_ERC_OK == NTSmartPublisherSDK.NT_PB_GetAuidoInputDeviceNumber(ref auido_devices))
            {
                if (auido_devices > 0)
                {
                    btn_check_auido_mic_input_.Enabled = true;

                    for (int i = 0; i < auido_devices; ++i)
                    {
                        byte[] deviceNameBuffer = new byte[512];

                        string name = "";

                        if (NTBaseCodeDefine.NT_ERC_OK == NTSmartPublisherSDK.NT_PB_GetAuidoInputDeviceName((uint)i, deviceNameBuffer, 512))
                        {
                            int count = 0;
                            for (int j = 0; j < deviceNameBuffer.Length; ++j )
                            {
                                if ( deviceNameBuffer[j] != 0 )
                                {
                                    count++;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            if ( count > 0 )
                            {
                                name = Encoding.UTF8.GetString(deviceNameBuffer, 0, count);
                            }                    
                        }

                        var audio_name = "";

                        if (name.Length == 0)
                        {
                            audio_name = "音频采集设备-";
                        }
                        else
                        {
                            audio_name = name + "-";
                        }

                        audio_name = audio_name + (i + 1);

                        combox_auido_input_devices_.Items.Add(name);
                    }
                    combox_auido_input_devices_.SelectedIndex = 0;
                }
            }

代码语言:javascript
复制
            publisher_handle_ = new IntPtr();

            region_choose_tool_handle_ = new IntPtr();

            win_form_wnd_ = GetForegroundWindow();

            cameras_ = new List<CameraInfo>();

            btn_check_video_bitrate_.CheckState = CheckState.Checked;

            if (IsCanCaptureSpeaker())
            {
                btn_check_auido_speaker_input_.Enabled = true;
            }
            else
            {
                btn_check_auido_speaker_input_.Enabled = false;
            }

            if (btn_check_auido_mic_input_.Checked
                  || btn_check_auido_speaker_input_.Checked)
            {
                btn_check_speex_encoder_.Enabled = true;
                edit_speex_quality_.Enabled = true;
                btn_check_noise_suppression_.Enabled = true;
                btn_check_agc_.Enabled = true;
                btn_check_vad_.Enabled = true;
            }

            if ( btn_check_auido_mic_input_.Checked
                && btn_check_auido_speaker_input_.Checked)
            {
                btn_check_echo_cancel_.Enabled = false;
                edit_echo_delay_.Enabled = false;
            }

            edit_audio_input_volume_.Text = "1.0";
            edit_audio_speaker_input_volume_.Text = "1.0";

            FillCameraInfo();
            InitCameraControl();

OpenPublisherHandle()

OpenPublisherHandle()主要是确认选择数据源类型,然后获取推送句柄,等待做下一步的操作。

选择video option和 audio option

代码语言:javascript
复制
            // 视频
            UInt32 video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_NO_VIDEO;

            if (btn_desktop_camera_switch.Checked
                || btn_camera_overlay_to_desktop.Checked
                || btn_desktop_overlay_to_camera.Checked)
            {
                // 使用叠加模式
                video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_LAYER;
            }
            else if (btn_check_window_input_.Checked)
            {
                video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_WINDOW;
            }
            else if (btn_check_desktop_input_.Checked && btn_check_scale_desktop_.Checked)
            {
                // 使用叠加模式来实现缩放
                video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_LAYER;
            }
            else if (btn_check_desktop_input_.Checked && !btn_check_scale_desktop_.Checked)
            {
                //屏幕模式
                video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_SCREEN;
            }
            else if (btn_check_camera_input_.Checked)
            {
                //摄像头模式
                video_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_VIDEO_OPTION.NT_PB_E_VIDEO_OPTION_CAMERA;
            }

            // 音频
            UInt32 audio_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_AUDIO_OPTION.NT_PB_E_AUDIO_OPTION_NO_AUDIO;

            if (btn_check_auido_mic_input_.Checked
                && btn_check_auido_speaker_input_.Checked)
            {
                audio_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_AUDIO_OPTION.NT_PB_E_AUDIO_OPTION_CAPTURE_MIC_SPEAKER_MIXER;
            }
            else if (btn_check_auido_mic_input_.Checked)
            {
                //麦克风模式
                audio_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_AUDIO_OPTION.NT_PB_E_AUDIO_OPTION_CAPTURE_MIC;
            }
            else if (btn_check_auido_speaker_input_.Checked)
            {
                //扬声器模式
                audio_option = (UInt32)NTSmartPublisherDefine.NT_PB_E_AUDIO_OPTION.NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER;
            }

调用Open接口获取publisher handle,然设置event callback

代码语言:javascript
复制
            if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_Open(out publisher_handle_,
                video_option, audio_option, 0, IntPtr.Zero))
            {
                MessageBox.Show("Call open failed!");
                return false;
            }

            if (publisher_handle_ != IntPtr.Zero)
            {
                pb_event_call_back_ = new NT_PB_SDKEventCallBack(PbSDKEventCallBack);

                NTSmartPublisherSDK.NT_PB_SetEventCallBack(publisher_handle_, win_form_wnd_, pb_event_call_back_);
                return true;
            }
            else
            {
                return false;
            }

event callback相关ID

代码语言:javascript
复制
        /*事件ID*/
        public enum NT_PB_E_EVENT_ID : uint
        {
            NT_PB_E_EVENT_ID_BASE = NTBaseCodeDefine.NT_EVENT_ID_SMART_PUBLISHER_SDK,

	        NT_PB_E_EVENT_ID_CONNECTING			= NT_PB_E_EVENT_ID_BASE | 0x2,	/*连接中, param5表示推送URL */
	        NT_PB_E_EVENT_ID_CONNECTION_FAILED	= NT_PB_E_EVENT_ID_BASE | 0x3,	/*连接失败, param5表示推送URL*/
	        NT_PB_E_EVENT_ID_CONNECTED			= NT_PB_E_EVENT_ID_BASE | 0x4,	/*已连接, param5表示推送URL*/
	        NT_PB_E_EVENT_ID_DISCONNECTED		= NT_PB_E_EVENT_ID_BASE | 0x5,	/*断开连接, param5表示推送URL*/
	
	        NT_PB_E_EVENT_ID_RECORDER_START_NEW_FILE    = NT_PB_E_EVENT_ID_BASE | 0x7,	/*录像写入新文件, param5表示录像文件名*/
	        NT_PB_E_EVENT_ID_ONE_RECORDER_FILE_FINISHED = NT_PB_E_EVENT_ID_BASE | 0x8,	/*一个录像文件完成, param5表示录像文件名*/

            NT_PB_E_EVENT_ID_CAPTURE_WINDOW_INVALID = NT_PB_E_EVENT_ID_BASE | 0xd, /*捕获窗口时,如果窗口句柄无效则通知用户, param1为窗口句柄*/

            NT_PB_E_EVENT_ID_RTSP_URL = NT_PB_E_EVENT_ID_BASE | 0xe, /* 通知rtsp url, param1表示rtsp server handle, param5 表示rtsp url */
            NT_PB_E_EVENT_ID_PUSH_RTSP_SERVER_RESPONSE_STATUS_CODE = NT_PB_E_EVENT_ID_BASE | 0xf,  /* 推送rtsp时服务端相应的status code上报,目前只上报401, param1表示status code,  param5表示推送URL */
            NT_PB_E_EVENT_ID_PUSH_RTSP_SERVER_NOT_SUPPORT = NT_PB_E_EVENT_ID_BASE | 0x10,  /* 推送rtsp时服务器不支持rtsp推送,  param5表示推送URL */
        }

SetCommonOptionToPublisherSDK()

SetCommonOptionToPublisherSDK()主要是指定具体采集的音视频数据类型,比如摄像头数据、屏幕数据、摄像头和屏幕叠加后的数据(以层级模式实现)、窗口等,这块比较复杂,好在作为SDK调用者,你只要搞清楚你需要采集的类型,直接移植就可以了。

音视频参数设定

其他音视频相关接口参数设定,比是否启用DXGI, Aero模式,软硬编码模式,帧率关键帧间隔码率等设定。

代码语言:javascript
复制
                if (btn_check_dxgi_screen_capturer_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_EnableDXGIScreenCapturer(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_EnableDXGIScreenCapturer(publisher_handle_, 0);
                }

                if (check_capture_layered_window_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_EnableScreenCaptureLayeredWindow(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_EnableScreenCaptureLayeredWindow(publisher_handle_, 0);
                }

                if (btn_check_capturer_disable_aero_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_DisableAeroScreenCapturer(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_DisableAeroScreenCapturer(publisher_handle_, 0);
                }

                if (btn_check_wr_way_capture_window_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetCaptureWindowWay(publisher_handle_, 2);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetCaptureWindowWay(publisher_handle_, 1);
                }

                int cur_video_codec_id = (int)NTCommonMediaDefine.NT_MEDIA_CODEC_ID.NT_MEDIA_CODEC_ID_H264;

                if (btn_check_h265_encoder_.Checked)
                {
                    cur_video_codec_id = (int)NTCommonMediaDefine.NT_MEDIA_CODEC_ID.NT_MEDIA_CODEC_ID_H265;
                }

                bool is_hw_encoder = false;

                if ( btn_check_video_hardware_encoder_.Checked)
                {
                    is_hw_encoder = true;
                }

                Int32 cur_sel_encoder_id = 0;
                Int32 cur_sel_gpu = 0;


                if (is_hw_encoder)
                {
                    int cur_sel_hw = combobox_video_encoders_.SelectedIndex;
                    if (cur_sel_hw >= 0)
                    {
                        cur_sel_encoder_id = Convert.ToInt32(combobox_video_encoders_.SelectedValue);
                        cur_sel_gpu = -1;

                        int cur_sel_hw_dev = combobox_video_hardware_encoder_devices_.SelectedIndex;
                        if (cur_sel_hw_dev >= 0)
                        {
                            cur_sel_gpu = Convert.ToInt32(combobox_video_hardware_encoder_devices_.SelectedValue);
                        }
                    }
                    else
                    {
                        is_hw_encoder = false;
                    }
                }

                if (!is_hw_encoder)
                {
                    if ((int)NTCommonMediaDefine.NT_MEDIA_CODEC_ID.NT_MEDIA_CODEC_ID_H264 == cur_video_codec_id)
                    {
                        cur_sel_encoder_id = btn_check_openh264_encoder_.Checked ? 1 : 0;
                    }
                }

                NTSmartPublisherSDK.NT_PB_SetVideoEncoder(publisher_handle_, (int)(is_hw_encoder ? 1 : 0), (int)cur_sel_encoder_id, (uint)cur_video_codec_id, (int)cur_sel_gpu);

                if (!btn_check_window_input_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetVideoBitRate(publisher_handle_, Int32.Parse(edit_bit_rate_.Text));
                }
                else
                {
                    // 窗口的分辨率会变, 所以设置一组码率下去
                    Int32 frame_rate = Int32.Parse(edit_bit_rate_.Text);
                    SetBitrateGroup(publisher_handle_, frame_rate);
                }

                NTSmartPublisherSDK.NT_PB_SetVideoQualityV2(publisher_handle_, Int32.Parse(edit_video_quality_.Text));

                NTSmartPublisherSDK.NT_PB_SetVideoMaxBitRate(publisher_handle_, Int32.Parse(edit_video_max_bitrate_.Text));

                NTSmartPublisherSDK.NT_PB_SetVideoKeyFrameInterval(publisher_handle_, Int32.Parse(edit_key_frame_.Text));

                if (cur_video_codec_id == (int)NTCommonMediaDefine.NT_MEDIA_CODEC_ID.NT_MEDIA_CODEC_ID_H264)
                {
                    int profile_sel = combox_h264_profile_.SelectedIndex;

                    if (profile_sel != -1)
                    {
                        NTSmartPublisherSDK.NT_PB_SetVideoEncoderProfile(publisher_handle_, profile_sel + 1);
                    }
                }

                NTSmartPublisherSDK.NT_PB_SetVideoEncoderSpeed(publisher_handle_, Int32.Parse(edit_video_encode_speed_.Text));

                // 清除编码器所有的特定的参数
                NTSmartPublisherSDK.NT_PB_ClearVideoEncoderSpecialOptions(publisher_handle_);

                if (cur_sel_encoder_id == 1)
                {
                    // qp_max 和 qp_min 当前只对openh264有效, 这里也就只在openh264使用的场景下设置配置值
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMax(publisher_handle_, Int32.Parse(edit_qp_max_.Text));
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMin(publisher_handle_, Int32.Parse(edit_qp_min_.Text));

                    // openh264 配置特定参数
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderSpecialInt32Option(publisher_handle_, "usage_type", btn_check_openh264_ppt_usage_type_.Checked ? 1 : 0);
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderSpecialInt32Option(publisher_handle_, "rc_mode", btn_check_openh264_rc_bitrate_mode_.Checked ? 1 : 0);
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderSpecialInt32Option(publisher_handle_, "enable_frame_skip", btn_check_openh264_frame_skip_.Checked ? 1 : 0);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMax(publisher_handle_, -1);
                    NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMin(publisher_handle_, -1);
                }

                // 音频相关设置
                if (btn_check_auido_mic_input_.Checked)
                {
                    int count = combox_auido_input_devices_.Items.Count;
                    if (count != -1 && count > 0)
                    {
                        int cur_sel = combox_auido_input_devices_.SelectedIndex;
                        if (cur_sel != -1)
                        {
                            NTSmartPublisherSDK.NT_PB_SetAuidoInputDeviceId(publisher_handle_, (uint)cur_sel);
                        }
                    }
                }

                // 只采集扬声器时做静音补偿
                if (!btn_check_auido_mic_input_.Checked
                    && btn_check_auido_speaker_input_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetCaptureSpeakerCompensateMute(publisher_handle_, 1);
                }

                if (btn_check_speex_encoder_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetPublisherAudioCodecType(publisher_handle_, 2);

                    NTSmartPublisherSDK.NT_PB_SetPublisherSpeexEncoderQuality(publisher_handle_, Int32.Parse(edit_speex_quality_.Text));
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetPublisherAudioCodecType(publisher_handle_, 1);
                }

                if (btn_check_auido_mic_input_.Checked
                    || btn_check_auido_speaker_input_.Checked)
                {
                    if (btn_check_set_mute_.Checked)
                    {
                        NTSmartPublisherSDK.NT_PB_SetMute(publisher_handle_, 1);
                    }
                }

                if (btn_check_echo_cancel_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetEchoCancellation(publisher_handle_, 1, Int32.Parse(edit_echo_delay_.Text));
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetEchoCancellation(publisher_handle_, 0, 0);
                }

                if (btn_check_noise_suppression_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetNoiseSuppression(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetNoiseSuppression(publisher_handle_, 0);
                }

                if (btn_check_agc_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetAGC(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetAGC(publisher_handle_, 0);
                }

                if (btn_check_vad_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetVAD(publisher_handle_, 1);
                }
                else
                {
                    NTSmartPublisherSDK.NT_PB_SetVAD(publisher_handle_, 0);
                }

                if (btn_check_auido_mic_input_.Checked
                    && btn_check_auido_speaker_input_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetInputAudioVolume(publisher_handle_, 0, Convert.ToSingle(edit_audio_input_volume_.Text));
                    NTSmartPublisherSDK.NT_PB_SetInputAudioVolume(publisher_handle_, 1, Convert.ToSingle(edit_audio_speaker_input_volume_.Text));
                }
                else if (btn_check_auido_mic_input_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetInputAudioVolume(publisher_handle_, 0, Convert.ToSingle(edit_audio_input_volume_.Text));
                }
                else if (btn_check_auido_speaker_input_.Checked)
                {
                    NTSmartPublisherSDK.NT_PB_SetInputAudioVolume(publisher_handle_, 0, Convert.ToSingle(edit_audio_speaker_input_volume_.Text));
                }

获取视频码率默认值,不是每个开发者都有音视频开发背景,如果不想自行设置码率等一些参数,可参考我们的码率设定。

代码语言:javascript
复制
       private void FillBitrateControlDefValue()
        {
            int w = 640, h = 480;
            int frame_rate = 5;
            bool is_var_bitrate = false;

            GetVideoConfigInfo(ref w, ref h, ref frame_rate, ref is_var_bitrate);

            if (btn_check_openh264_encoder_.Checked)
            {
                is_var_bitrate = false;
            }

            int kbit_rate = CalBitRate(frame_rate, w, h);
            int max_kbit_rate = CalMaxKBitRate(frame_rate, w, h, is_var_bitrate);

            if (is_var_bitrate)
            {
                btn_check_video_bitrate_.CheckState = CheckState.Unchecked;
            }
            else
            {
                btn_check_video_bitrate_.CheckState = CheckState.Checked;
            }

            if (is_var_bitrate)
            {
                edit_bit_rate_.Enabled = false;
                edit_video_quality_.Enabled = true;
            }
            else
            {
                edit_bit_rate_.Enabled = true;
                edit_video_quality_.Enabled = false;
            }

            if (btn_check_video_bitrate_.Checked)
            {
                edit_bit_rate_.Text = kbit_rate.ToString();
                edit_video_max_bitrate_.Text = max_kbit_rate.ToString();
            }
            else
            {
                edit_bit_rate_.Text = "0";
                edit_video_max_bitrate_.Text = max_kbit_rate.ToString();
            }

            bool is_h264 = false;

            if (btn_check_h265_encoder_.Checked)
            {
                is_h264 = false;
            }
            else
            {
                is_h264 = true;
            }

            edit_video_quality_.Text = CalVideoQuality(w, h, is_h264).ToString();

            combox_h264_profile_.SelectedIndex = 2;

            edit_video_encode_speed_.Text = CalVideoEncoderSpeed(w, h, is_h264).ToString();

            // 默认关键帧间隔设置为帧率的2倍
            edit_key_frame_.Text = (frame_rate * 2).ToString();
        }

开始推送

设置推送URL后,调用StartPublisher接口开始推流,如需发送扩展SEI用户数据,推送之前设置下数据发送对接大小。

代码语言:javascript
复制
            if (publisher_handle_ == IntPtr.Zero)
            {
                MessageBox.Show("[publish] handle with null");
            }
            if (!String.IsNullOrEmpty(url))
	        {
                NTSmartPublisherSDK.NT_PB_SetURL(publisher_handle_, url, IntPtr.Zero);
	        }

            //设置用户数据发送队列大小
            NTSmartPublisherSDK.NT_PB_SetPostUserDataQueueMaxSize(publisher_handle_, 3, 0);

            if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartPublisher(publisher_handle_, IntPtr.Zero))
            {
                if (0 == publisher_handle_count_)
                {
                    NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                    publisher_handle_ = IntPtr.Zero;
                }

                is_publishing_ = false;

                MessageBox.Show("调用推流接口失败");

                return;
            }

停止推送

调用NT_PB_StopPublisher()即可,停止推送后,如果没有录像等,可调用NT_PB_Close()接口,关掉实例,并把handle置 IntPtr.Zero。

代码语言:javascript
复制
        private void btn_stop_publish_Click(object sender, EventArgs e)
        {
            publisher_handle_count_--;
            NTSmartPublisherSDK.NT_PB_StopPublisher(publisher_handle_);

            rtmp_play_urls_.Clear();
            UpdateDisplayURLs();

            if (0 == publisher_handle_count_)
            {
                NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                publisher_handle_ = IntPtr.Zero;
            }

            btn_publish.Enabled = true;
            btn_stop_publish.Enabled = false;

            is_publishing_ = false;

            if (0 == publisher_handle_count_)
            {
                if (btn_check_desktop_input_.Checked)
                {
                    btn_choose_screen_region_.Text = "选择屏幕区域";
                }

                btn_check_dxgi_screen_capturer_.Enabled = true;
                check_capture_layered_window_.Enabled = true;

                btn_check_wr_way_capture_window_.Enabled = true;

                btn_desktop_camera_switch_.Text = "切换到摄像头";
                btn_disable_image_watermark_.Text = "停止水印";
                btn_disable_camera_overlay_.Text = "停止叠加摄像头";
                btn_disable_desktop_overlay_.Text = "停止叠加屏幕";

                btn_desktop_camera_switch.Enabled = true;
                btn_camera_overlay_to_desktop.Enabled = true;
                btn_desktop_overlay_to_camera.Enabled = true;
                btn_desktop_camera_switch.Enabled = true;

                btn_check_desktop_input_.Enabled = true;
                btn_check_scale_desktop_.Enabled = true;
                edit_desktop_scale_.Enabled = true;
                btn_check_camera_input_.Enabled = true;

                btn_add_image_watermark_.Enabled = true;

                timer_clock_.Enabled = false;

                if (btn_desktop_camera_switch.Checked
                    || btn_camera_overlay_to_desktop.Checked
                    || btn_desktop_overlay_to_camera.Checked)
                {
                    btn_check_desktop_input_.CheckState = CheckState.Checked;
                    btn_check_camera_input_.CheckState = CheckState.Checked;
                }
                else
                {
                }

                EnableAuidoInputControl();
            }
        }

预览推送数据

设置NT_PB_SetVideoPreviewImageCallBack(),调用NT_PB_StartPreview()接口即可。

代码语言:javascript
复制
        private void btn_preview_Click(object sender, EventArgs e)
        {
            if (btn_check_window_input_.Checked)
            {
                if (IntPtr.Zero == cur_sel_capture_window_)
                {
                    MessageBox.Show("请先下拉选择采集窗口");
                    return;
                }
            }

            if (publisher_handle_ == IntPtr.Zero)
            {
                if (!OpenPublisherHandle())
                {
                    return;
                }
            }

            if (publisher_handle_count_ < 1)
            {
                SetCommonOptionToPublisherSDK();
            }

            video_preview_image_callback_ = new NT_PB_SDKVideoPreviewImageCallBack(SDKVideoPreviewImageCallBack);

            NTSmartPublisherSDK.NT_PB_SetVideoPreviewImageCallBack(publisher_handle_, (int)NTSmartPublisherDefine.NT_PB_E_IMAGE_FORMAT.NT_PB_E_IMAGE_FORMAT_RGB32, IntPtr.Zero, video_preview_image_callback_);

            if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartPreview(publisher_handle_, 0, IntPtr.Zero))
            {
                if (0 == publisher_handle_count_)
                {
                    NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                    publisher_handle_ = IntPtr.Zero;
                }

                 MessageBox.Show("预览失败, 请确保选择了视频采集选项");
                return;
            }

            publisher_handle_count_++;

            btn_preview.Enabled = false;
            btn_stop_preview.Enabled = true;

            if (1 == publisher_handle_count_)
            {
                if (btn_check_desktop_input_.Checked)
                {
                    btn_choose_screen_region_.Text = "移动屏幕区域";
                }

                btn_check_dxgi_screen_capturer_.Enabled = false;
                check_capture_layered_window_.Enabled = false;

                btn_check_wr_way_capture_window_.Enabled = false;

                btn_desktop_camera_switch.Enabled = false;
                btn_camera_overlay_to_desktop.Enabled = false;
                btn_desktop_overlay_to_camera.Enabled = false;

                btn_add_image_watermark_.Enabled = false;

                if (btn_desktop_camera_switch.Checked
                    || btn_camera_overlay_to_desktop.Checked
                    || btn_desktop_overlay_to_camera.Checked)
                {

                }
                else
                {
                    btn_check_desktop_input_.Enabled = false;
                    btn_check_camera_input_.Enabled = false;
                }

                DisableAuidoInputControl();
            }

            if (ui_preview_wnd_ == null)
            {
                ui_preview_wnd_ = new nt_pb_ui_preview_wnd();
            }

            ui_preview_wnd_.Show();
        }

代码语言:javascript
复制
        public void VideoPreviewImageCallBack(NT_VideoFrame frame)
        {
            if (cur_image_.plane_ != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(cur_image_.plane_);
                cur_image_.plane_ = IntPtr.Zero;
            }

            cur_image_ = frame;

            if (ui_preview_wnd_ != null)
            {
                ui_preview_wnd_.OnRGBXImage(cur_image_);
            }
        }

        public void SDKVideoPreviewImageCallBack(IntPtr handle, IntPtr user_data, IntPtr image)
        {
            NT_PB_Image pb_image = (NT_PB_Image)Marshal.PtrToStructure(image, typeof(NT_PB_Image));

            NT_VideoFrame pVideoFrame = new NT_VideoFrame();

            pVideoFrame.width_ = pb_image.width_;
            pVideoFrame.height_ = pb_image.height_;

            pVideoFrame.stride_ = pb_image.stride_[0];

            Int32 argb_size = pb_image.stride_[0] * pb_image.height_;
            
            pVideoFrame.plane_ = Marshal.AllocHGlobal(argb_size);

            CopyMemory(pVideoFrame.plane_, pb_image.plane_[0], (UInt32)argb_size);

            if (InvokeRequired)
            {
                BeginInvoke(set_video_preview_image_callback_, pVideoFrame);
            }
            else
            {
                set_video_preview_image_callback_(pVideoFrame);
            }
        }

停止预览更简单,调用NT_PB_StopPreview()。

代码语言:javascript
复制
        private void btn_stop_preview_Click(object sender, EventArgs e)
        {
            publisher_handle_count_--;
            NTSmartPublisherSDK.NT_PB_StopPreview(publisher_handle_);

            if (0 == publisher_handle_count_)
            {
                NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                publisher_handle_ = IntPtr.Zero;
            }

            btn_preview.Enabled = true;
            btn_stop_preview.Enabled = false;

            if (0 == publisher_handle_count_)
            {
                if (btn_check_desktop_input_.Checked)
                {
                    btn_choose_screen_region_.Text = "选择屏幕区域";
                }

                btn_check_dxgi_screen_capturer_.Enabled = true;
                check_capture_layered_window_.Enabled = true;

                btn_check_wr_way_capture_window_.Enabled = true;

                btn_desktop_camera_switch_.Text = "切换到摄像头";
                btn_disable_image_watermark_.Text = "停止水印";
                btn_disable_camera_overlay_.Text = "停止叠加摄像头";
                btn_disable_desktop_overlay_.Text = "停止叠加屏幕";

                btn_desktop_camera_switch.Enabled = true;
                btn_camera_overlay_to_desktop.Enabled = true;
                btn_desktop_overlay_to_camera.Enabled = true;
                btn_desktop_camera_switch.Enabled = true;

                btn_check_desktop_input_.Enabled = true;
                btn_check_camera_input_.Enabled = true;

                btn_add_image_watermark_.Enabled = true;

                timer_clock_.Enabled = false;

                if (btn_desktop_camera_switch.Checked
                    || btn_camera_overlay_to_desktop.Checked
                    || btn_desktop_overlay_to_camera.Checked)
                {
                    btn_check_desktop_input_.CheckState = CheckState.Checked;
                    btn_check_camera_input_.CheckState = CheckState.Checked;
                }
                else
                {
                }

                EnableAuidoInputControl();
            }

            ui_preview_wnd_.Hide();
            ui_preview_wnd_ = null;
        }

实时截图

代码语言:javascript
复制
            if (String.IsNullOrEmpty(capture_image_path_))
            {
                MessageBox.Show("请先设置保存截图文件的目录! 点击截图左边的按钮设置!");
                return;
            }

            if (publisher_handle_ == IntPtr.Zero)
            {
                return;
            }

            String name = capture_image_path_ + "\\" + DateTime.Now.ToString("hh-mm-ss") + ".png";

            byte[] buffer1 = Encoding.Default.GetBytes(name);
            byte[] buffer2 = Encoding.Convert(Encoding.Default, Encoding.UTF8, buffer1, 0, buffer1.Length);

            byte[] buffer3 = new byte[buffer2.Length + 1];
            buffer3[buffer2.Length] = 0;

            Array.Copy(buffer2, buffer3, buffer2.Length);

            IntPtr file_name_ptr = Marshal.AllocHGlobal(buffer3.Length);
            Marshal.Copy(buffer3, 0, file_name_ptr, buffer3.Length);

            capture_image_call_back_ = new NT_PB_SDKCaptureImageCallBack(SDKCaptureImageCallBack);

            UInt32 ret = NTSmartPublisherSDK.NT_PB_CaptureImage(publisher_handle_, file_name_ptr, IntPtr.Zero, capture_image_call_back_);

            Marshal.FreeHGlobal(file_name_ptr);

            if (NT.NTBaseCodeDefine.NT_ERC_OK == ret)
            {
                // 发送截图请求成功
            }
            else if ((UInt32)NT.NTSmartPublisherDefine.NT_PB_E_ERROR_CODE.NT_ERC_PB_TOO_MANY_CAPTURE_IMAGE_REQUESTS == ret)
            {
                // 通知用户延时
                MessageBox.Show("Too many capture image requests!");
            }
            else
            {
                // 其他失败
            }

代码语言:javascript
复制
       private void ImageCallBack(UInt32 result, String file_name)
        {
            if (file_name == null && file_name.Length == 0)
                return;

            MessageBox.Show(file_name);
        }

        public void SDKCaptureImageCallBack(IntPtr handle, IntPtr userData, UInt32 result, IntPtr file_name)
        {
            if (file_name == IntPtr.Zero)
                return;

            int index = 0;

            while (true)
            {
                if (0 == Marshal.ReadByte(file_name, index))
                    break;

                index++;
            }

            byte[] file_name_buffer = new byte[index];

            Marshal.Copy(file_name, file_name_buffer, 0, index);

            byte[] dst_buffer = Encoding.Convert(Encoding.UTF8, Encoding.Default, file_name_buffer, 0, file_name_buffer.Length);
            String image_name = Encoding.Default.GetString(dst_buffer, 0, dst_buffer.Length);

            if (InvokeRequired)
            {
                BeginInvoke(set_capture_image_call_back_, result, image_name);
            }
            else
            {
                set_capture_image_call_back_(result, image_name);
            }
        }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 初始化
  • OpenPublisherHandle()
  • event callback相关ID
  • SetCommonOptionToPublisherSDK()
  • 音视频参数设定
  • 开始推送
  • 停止推送
  • 预览推送数据
  • 实时截图
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档