好多开发者在集成大牛直播SDK (官方)的Windows平台RTMP推送模块时吓一跳,怎么这么多接口?本文做个简单的拆分:
初始化
初始化之前,如需设置日志路径,调用NTSmartLog.NT_SL_SetPath(log_path); 设置日志存放路径。
设置过后,调用NT_PB_Init()接口,完成SDK初始化动作,注意,哪怕多实例推送,Init()接口也仅需调一次,同理,UnInit()接口也是。
然后,代码会判断系统是不是支持WR模式采集窗口,WR这种只有Win10高版本的才支持,如果不需要用到采集窗口,这个接口可忽略。
再往下,是遍历系统支持的硬解、摄像头等信息,比如LoadHWVideoEncoderInfos():
紧接着是Audio和camera相关:
OpenPublisherHandle()
OpenPublisherHandle()主要是确认选择数据源类型,然后获取推送句柄,等待做下一步的操作。
选择video option和 audio option
调用Open接口获取publisher handle,然设置event callback
event callback相关ID
SetCommonOptionToPublisherSDK()
SetCommonOptionToPublisherSDK()主要是指定具体采集的音视频数据类型,比如摄像头数据、屏幕数据、摄像头和屏幕叠加后的数据(以层级模式实现)、窗口等,这块比较复杂,好在作为SDK调用者,你只要搞清楚你需要采集的类型,直接移植就可以了。
if (btn_desktop_camera_switch.Checked
|| btn_camera_overlay_to_desktop.Checked
|| btn_desktop_overlay_to_camera.Checked
|| btn_check_desktop_input_.Checked
|| btn_check_window_input_.Checked
|| btn_check_camera_input_.Checked)
{
if (btn_desktop_camera_switch.Checked)
{
int left = Int32.Parse(edit_clip_left_.Text);
int top = Int32.Parse(edit_clip_top_.Text);
int w = Int32.Parse(edit_clip_width_.Text);
int h = Int32.Parse(edit_clip_height_.Text);
if (w == 0 || h == 0)
{
left = 0;
top = 0;
w = screenArea_.Width;
h = screenArea_.Height;
}
else
{
w = NT_ByteAlign(w, 4);
h = NT_ByteAlign(h, 4);
}
NTSmartPublisherSDK.NT_PB_ClearLayersConfig(publisher_handle_, 0,
0, IntPtr.Zero);
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
NT_PB_RGBARectangleLayerConfig rgba_layer_c0 = new NT_PB_RGBARectangleLayerConfig();
rgba_layer_c0.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE;
rgba_layer_c0.base_.index_ = 0;
rgba_layer_c0.base_.enable_ = 1;
rgba_layer_c0.base_.region_.x_ = left;
rgba_layer_c0.base_.region_.y_ = top;
rgba_layer_c0.base_.region_.width_ = w;
rgba_layer_c0.base_.region_.height_ = h;
rgba_layer_c0.base_.offset_ = Marshal.OffsetOf(rgba_layer_c0.GetType(), "base_").ToInt32();
rgba_layer_c0.base_.cb_size_ = (uint)Marshal.SizeOf(rgba_layer_c0);
rgba_layer_c0.red_ = System.BitConverter.GetBytes(red)[0];
rgba_layer_c0.green_ = System.BitConverter.GetBytes(green)[0];
rgba_layer_c0.blue_ = System.BitConverter.GetBytes(blue)[0];
rgba_layer_c0.alpha_ = System.BitConverter.GetBytes(alpha)[0];
IntPtr rgba_conf = Marshal.AllocHGlobal(Marshal.SizeOf(rgba_layer_c0));
Marshal.StructureToPtr(rgba_layer_c0, rgba_conf, true);
UInt32 rgba_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
rgba_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE,
0, IntPtr.Zero);
Console.WriteLine("[摄像头和屏幕相互切换] NT_PB_AddLayerConfig, rgba: " + rgba_r + Environment.NewLine);
Marshal.FreeHGlobal(rgba_conf);
NT_PB_CameraLayerConfigV2 camera_layer_c1 = new NT_PB_CameraLayerConfigV2();
CameraInfo camera = cameras_[cur_sel_camera_index_];
NT_PB_VideoCaptureCapability cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
camera_layer_c1.device_unique_id_utf8_ = camera.id_;
camera_layer_c1.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA;
camera_layer_c1.base_.index_ = 1;
camera_layer_index_ = camera_layer_c1.base_.index_;
camera_layer_c1.base_.enable_ = 1;
camera_layer_c1.base_.region_.x_ = left;
camera_layer_c1.base_.region_.y_ = top;
camera_layer_c1.base_.region_.width_ = w;
camera_layer_c1.base_.region_.height_ = h;
if (btn_check_flip_horizontal_camera_.Checked)
{
camera_layer_c1.is_flip_horizontal_ = 1;
}
else
{
camera_layer_c1.is_flip_horizontal_ = 0;
}
if (btn_check_flip_vertical_camera_.Checked)
{
camera_layer_c1.is_flip_vertical_ = 1;
}
else
{
camera_layer_c1.is_flip_vertical_ = 0;
}
camera_layer_c1.rotate_degress_ = 0;
camera_layer_c1.base_.offset_ = Marshal.OffsetOf(camera_layer_c1.GetType(), "base_").ToInt32();
camera_layer_c1.base_.cb_size_ = (uint)Marshal.SizeOf(camera_layer_c1);
IntPtr cmr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(camera_layer_c1));
Marshal.StructureToPtr(camera_layer_c1, cmr_conf, true);
UInt32 c_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
cmr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA,
0, IntPtr.Zero);
Marshal.FreeHGlobal(cmr_conf);
NT_PB_ScreenLayerConfig screen_layer_c2 = new NT_PB_ScreenLayerConfig();
screen_layer_c2.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN;
screen_layer_c2.base_.index_ = 2;
screen_layer_index_ = screen_layer_c2.base_.index_;
screen_layer_c2.base_.enable_ = 1;
screen_layer_c2.base_.region_.x_ = left;
screen_layer_c2.base_.region_.y_ = top;
screen_layer_c2.base_.region_.width_ = w;
screen_layer_c2.base_.region_.height_ = h;
screen_layer_c2.base_.offset_ = Marshal.OffsetOf(screen_layer_c2.GetType(), "base_").ToInt32();
screen_layer_c2.base_.cb_size_ = (uint)Marshal.SizeOf(screen_layer_c2);
screen_layer_c2.clip_region_.x_ = left;
screen_layer_c2.clip_region_.y_ = top;
screen_layer_c2.clip_region_.width_ = w;
screen_layer_c2.clip_region_.height_ = h;
screen_layer_c2.reserve_ = IntPtr.Zero;
IntPtr scr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(screen_layer_c2));
Marshal.StructureToPtr(screen_layer_c2, scr_conf, true);
UInt32 s_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
scr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN,
0, IntPtr.Zero);
Marshal.FreeHGlobal(scr_conf);
red = Int32.Parse(edit_rgba_rect_layer_red_.Text);
red = ClipIntValue(red, 0, 255);
green = Int32.Parse(edit_rgba_rect_layer_green_.Text);
green = ClipIntValue(green, 0, 255);
blue = Int32.Parse(edit_rgba_rect_layer_blue_.Text);
blue = ClipIntValue(blue, 0, 255);
alpha = Int32.Parse(edit_rgba_rect_layer_alpha_.Text);
alpha = ClipIntValue(alpha, 0, 255);
NT_PB_RGBARectangleLayerConfig rgba_layer_c3 = new NT_PB_RGBARectangleLayerConfig();
rgba_layer_c3.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE;
rgba_layer_c3.base_.index_ = 3;
rgba_layer_index_ = rgba_layer_c3.base_.index_;
rgba_layer_c3.base_.enable_ = 1;
rgba_layer_c3.base_.region_.x_ = left;
rgba_layer_c3.base_.region_.y_ = top;
rgba_layer_c3.base_.region_.width_ = 160;
rgba_layer_c3.base_.region_.height_ = 160;
rgba_layer_c3.base_.offset_ = Marshal.OffsetOf(rgba_layer_c3.GetType(), "base_").ToInt32();
rgba_layer_c3.base_.cb_size_ = (uint)Marshal.SizeOf(rgba_layer_c3);
rgba_layer_c3.red_ = System.BitConverter.GetBytes(red)[0];
rgba_layer_c3.green_ = System.BitConverter.GetBytes(green)[0];
rgba_layer_c3.blue_ = System.BitConverter.GetBytes(blue)[0];
rgba_layer_c3.alpha_ = System.BitConverter.GetBytes(alpha)[0];
IntPtr rgba_conf_3 = Marshal.AllocHGlobal(Marshal.SizeOf(rgba_layer_c3));
Marshal.StructureToPtr(rgba_layer_c3, rgba_conf_3, true);
UInt32 rgba_r_3 = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
rgba_conf_3, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE,
0, IntPtr.Zero);
Console.WriteLine("NT_PB_AddLayerConfig, rgba: " + rgba_r_3 + Environment.NewLine);
Marshal.FreeHGlobal(rgba_conf_3);
if (!String.IsNullOrEmpty(image_layer_file_name_utf8_)
&& image_layer_width_ > 0
&& image_layer_height_ > 0)
{
NT_PB_ImageLayerConfig image_layer_c4 = new NT_PB_ImageLayerConfig();
image_layer_c4.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_IMAGE;
image_layer_c4.base_.index_ = 4;
image_layer_index_ = image_layer_c4.base_.index_;
image_layer_c4.base_.enable_ = 1;
image_layer_c4.base_.region_.x_ = image_layer_left_;
image_layer_c4.base_.region_.y_ = image_layer_top_;
image_layer_c4.base_.region_.width_ = image_layer_width_;
image_layer_c4.base_.region_.height_ = image_layer_height_;
image_layer_c4.base_.offset_ = Marshal.OffsetOf(image_layer_c4.GetType(), "base_").ToInt32();
image_layer_c4.base_.cb_size_ = (uint)Marshal.SizeOf(image_layer_c4);
byte[] buffer1 = Encoding.Default.GetBytes(image_layer_file_name_utf8_);
byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);
string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);
image_layer_c4.file_name_utf8_ = strBuffer;
image_layer_c4.is_setting_background_ = 0;
image_layer_c4.bk_red_ = 0;
image_layer_c4.bk_green_ = 0;
image_layer_c4.bk_blue_ = 0;
image_layer_c4.reserve_ = 0;
IntPtr image_conf = Marshal.AllocHGlobal(Marshal.SizeOf(image_layer_c4));
Marshal.StructureToPtr(image_layer_c4, image_conf, true);
UInt32 image_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
image_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_IMAGE,
0, IntPtr.Zero);
Console.WriteLine("NT_PB_AddLayerConfig, image: " + image_r + Environment.NewLine);
Marshal.FreeHGlobal(image_conf);
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, UInt32.Parse(edit_frame_rate_.Text));
}
}
else if (btn_camera_overlay_to_desktop.Checked)
{
int left = Int32.Parse(edit_clip_left_.Text);
int top = Int32.Parse(edit_clip_top_.Text);
int w = Int32.Parse(edit_clip_width_.Text);
int h = Int32.Parse(edit_clip_height_.Text);
if ( w == 0 || h == 0 )
{
left = 0;
top = 0;
w = screenArea_.Width;
h = screenArea_.Height;
}
else
{
w = NT_ByteAlign(w, 4);
h = NT_ByteAlign(h, 4);
}
NT_PB_ScreenLayerConfig screen_layer_c0 = new NT_PB_ScreenLayerConfig();
screen_layer_c0.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN;
screen_layer_c0.base_.index_ = 0;
screen_layer_index_ = screen_layer_c0.base_.index_;
screen_layer_c0.base_.enable_ = 1;
screen_layer_c0.base_.region_.x_ = left;
screen_layer_c0.base_.region_.y_ = top;
screen_layer_c0.base_.region_.width_ = w;
screen_layer_c0.base_.region_.height_ = h;
screen_layer_c0.base_.offset_ = Marshal.OffsetOf(screen_layer_c0.GetType(), "base_").ToInt32();
screen_layer_c0.base_.cb_size_ = (uint)Marshal.SizeOf(screen_layer_c0);
screen_layer_c0.clip_region_.x_ = left;
screen_layer_c0.clip_region_.y_ = top;
screen_layer_c0.clip_region_.width_ = w;
screen_layer_c0.clip_region_.height_ = h;
screen_layer_c0.reserve_ = IntPtr.Zero;
NTSmartPublisherSDK.NT_PB_ClearLayersConfig(publisher_handle_, 0,
0, IntPtr.Zero);
IntPtr scr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(screen_layer_c0));
Marshal.StructureToPtr(screen_layer_c0, scr_conf, true);
UInt32 s_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
scr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN,
0, IntPtr.Zero);
Marshal.FreeHGlobal(scr_conf);
if (-1 != cur_sel_camera_index_)
{
int c_l = Int32.Parse(edit_camera_overlay_left_.Text);
int c_t = Int32.Parse(edit_camera_overlay_top_.Text);
int c_w = Int32.Parse(edit_camera_overlay_width_.Text);
int c_h = Int32.Parse(edit_camera_overlay_height_.Text);
if (c_w == 0)
{
c_w = w / 2;
}
if (c_h == 0)
{
c_h = h / 2;
}
ctos_camera_layer_c1_ = new NT_PB_CameraLayerConfigV2();
CameraInfo camera = cameras_[cur_sel_camera_index_];
NT_PB_VideoCaptureCapability cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
ctos_camera_layer_c1_.device_unique_id_utf8_ = camera.id_;
ctos_camera_layer_c1_.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA;
ctos_camera_layer_c1_.base_.index_ = 1;
camera_layer_index_ = ctos_camera_layer_c1_.base_.index_;
ctos_camera_layer_c1_.base_.enable_ = 1;
ctos_camera_layer_c1_.base_.region_.x_ = c_l;
ctos_camera_layer_c1_.base_.region_.y_ = c_t;
ctos_camera_layer_c1_.base_.region_.width_ = c_w;
ctos_camera_layer_c1_.base_.region_.height_ = c_h;
if (btn_check_flip_horizontal_camera_.Checked)
{
ctos_camera_layer_c1_.is_flip_horizontal_ = 1;
}
else
{
ctos_camera_layer_c1_.is_flip_horizontal_ = 0;
}
if (btn_check_flip_vertical_camera_.Checked)
{
ctos_camera_layer_c1_.is_flip_vertical_ = 1;
}
else
{
ctos_camera_layer_c1_.is_flip_vertical_ = 0;
}
ctos_camera_layer_c1_.rotate_degress_ = GetCameraRotateDegress();
ctos_camera_layer_c1_.base_.offset_ = Marshal.OffsetOf(ctos_camera_layer_c1_.GetType(), "base_").ToInt32();
ctos_camera_layer_c1_.base_.cb_size_ = (uint)Marshal.SizeOf(ctos_camera_layer_c1_);
IntPtr cmr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(ctos_camera_layer_c1_));
Marshal.StructureToPtr(ctos_camera_layer_c1_, cmr_conf, true);
UInt32 c_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
cmr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA,
0, IntPtr.Zero);
Marshal.FreeHGlobal(cmr_conf);
}
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, UInt32.Parse(edit_frame_rate_.Text));
}
else if (btn_desktop_overlay_to_camera.Checked)
{
if (-1 != cur_sel_camera_index_
&& -1 != cur_sel_camera_resolutions_index_
&& -1 != cur_sel_camera_frame_rate_index_)
{
NT_PB_CameraLayerConfigV2 camera_layer_c0 = new NT_PB_CameraLayerConfigV2();
CameraInfo camera = cameras_[cur_sel_camera_index_];
NT_PB_VideoCaptureCapability cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
camera_layer_c0.device_unique_id_utf8_ = camera.id_;
camera_layer_c0.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA;
camera_layer_c0.base_.index_ = 0;
camera_layer_index_ = camera_layer_c0.base_.index_;
camera_layer_c0.base_.enable_ = 1;
camera_layer_c0.base_.region_.x_ = 0;
camera_layer_c0.base_.region_.y_ = 0;
camera_layer_c0.base_.region_.width_ = cap.width_;
camera_layer_c0.base_.region_.height_ = cap.height_;
if (btn_check_flip_horizontal_camera_.Checked)
{
camera_layer_c0.is_flip_horizontal_ = 1;
}
else
{
camera_layer_c0.is_flip_horizontal_ = 0;
}
if (btn_check_flip_vertical_camera_.Checked)
{
camera_layer_c0.is_flip_vertical_ = 1;
}
else
{
camera_layer_c0.is_flip_vertical_ = 0;
}
camera_layer_c0.rotate_degress_ = 0;
camera_layer_c0.base_.offset_ = Marshal.OffsetOf(camera_layer_c0.GetType(), "base_").ToInt32();
camera_layer_c0.base_.cb_size_ = (uint)Marshal.SizeOf(camera_layer_c0);
NTSmartPublisherSDK.NT_PB_ClearLayersConfig(publisher_handle_, 0,
0, IntPtr.Zero);
IntPtr cmr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(camera_layer_c0));
Marshal.StructureToPtr(camera_layer_c0, cmr_conf, true);
UInt32 r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
cmr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_CAMERA,
0, IntPtr.Zero);
Marshal.FreeHGlobal(cmr_conf);
NT_PB_ScreenLayerConfig screen_layer_c1 = new NT_PB_ScreenLayerConfig();
screen_layer_c1.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN;
screen_layer_c1.base_.index_ = 1;
screen_layer_index_ = screen_layer_c1.base_.index_;
screen_layer_c1.base_.enable_ = 1;
screen_layer_c1.base_.region_.x_ = 0;
screen_layer_c1.base_.region_.y_ = 0;
screen_layer_c1.base_.region_.width_ = cap.width_ / 2;
screen_layer_c1.base_.region_.height_ = cap.height_ / 2;
screen_layer_c1.base_.offset_ = Marshal.OffsetOf(screen_layer_c1.GetType(), "base_").ToInt32();
screen_layer_c1.base_.cb_size_ = (uint)Marshal.SizeOf(screen_layer_c1);
screen_layer_c1.clip_region_.x_ = 0;
screen_layer_c1.clip_region_.y_ = 0;
screen_layer_c1.clip_region_.width_ = cap.width_ / 2;
screen_layer_c1.clip_region_.height_ = cap.height_ / 2;
screen_layer_c1.reserve_ = IntPtr.Zero;
IntPtr scr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(screen_layer_c1));
Marshal.StructureToPtr(screen_layer_c1, scr_conf, true);
UInt32 s_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
scr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN,
0, IntPtr.Zero);
Marshal.FreeHGlobal(scr_conf);
}
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, (uint)(cur_sel_camera_frame_rate_index_ + 1));
}
else if (btn_check_desktop_input_.Checked && btn_check_scale_desktop_.Checked)
{
int left = 0;
int top = 0;
int w = 0;
int h = 0;
int scale_w = 0;
int scale_h = 0;
GetScreenScaleConfigInfo(ref left, ref top, ref w, ref h, ref scale_w, ref scale_h);
NTSmartPublisherSDK.NT_PB_ClearLayersConfig(publisher_handle_, 0,
0, IntPtr.Zero);
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
NT_PB_RGBARectangleLayerConfig rgba_layer_c0 = new NT_PB_RGBARectangleLayerConfig();
rgba_layer_c0.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE;
rgba_layer_c0.base_.index_ = 0;
rgba_layer_index_ = rgba_layer_c0.base_.index_;
rgba_layer_c0.base_.enable_ = 1;
rgba_layer_c0.base_.region_.x_ = 0;
rgba_layer_c0.base_.region_.y_ = 0;
rgba_layer_c0.base_.region_.width_ = scale_w;
rgba_layer_c0.base_.region_.height_ = scale_h;
rgba_layer_c0.base_.offset_ = Marshal.OffsetOf(rgba_layer_c0.GetType(), "base_").ToInt32();
rgba_layer_c0.base_.cb_size_ = (uint)Marshal.SizeOf(rgba_layer_c0);
rgba_layer_c0.red_ = 0;
rgba_layer_c0.green_ = 0;
rgba_layer_c0.blue_ = 0;
rgba_layer_c0.alpha_ = 255;
IntPtr rgba_conf_0 = Marshal.AllocHGlobal(Marshal.SizeOf(rgba_layer_c0));
Marshal.StructureToPtr(rgba_layer_c0, rgba_conf_0, true);
UInt32 rgba_r_0 = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
rgba_conf_0, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_RGBA_RECTANGLE,
0, IntPtr.Zero);
Console.WriteLine("NT_PB_AddLayerConfig, rgba: " + rgba_r_0 + Environment.NewLine);
Marshal.FreeHGlobal(rgba_conf_0);
NT_PB_ScreenLayerConfigV2 screen_layer_c1 = new NT_PB_ScreenLayerConfigV2();
screen_layer_c1.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN;
screen_layer_c1.base_.index_ = 1;
screen_layer_index_ = screen_layer_c1.base_.index_;
screen_layer_c1.base_.enable_ = checkbox_black_screen_.Checked?0:1;
screen_layer_c1.base_.region_.x_ = left;
screen_layer_c1.base_.region_.y_ = top;
screen_layer_c1.base_.region_.width_ = scale_w;
screen_layer_c1.base_.region_.height_ = scale_h;
screen_layer_c1.base_.offset_ = Marshal.OffsetOf(screen_layer_c1.GetType(), "base_").ToInt32();
screen_layer_c1.base_.cb_size_ = (uint)Marshal.SizeOf(screen_layer_c1);
screen_layer_c1.clip_region_.x_ = left;
screen_layer_c1.clip_region_.y_ = top;
screen_layer_c1.clip_region_.width_ = w;
screen_layer_c1.clip_region_.height_ = h;
screen_layer_c1.reserve1_ = IntPtr.Zero;
screen_layer_c1.reserve2_ = 0;
screen_layer_c1.scale_filter_mode_ = 3;
IntPtr scr_conf = Marshal.AllocHGlobal(Marshal.SizeOf(screen_layer_c1));
Marshal.StructureToPtr(screen_layer_c1, scr_conf, true);
UInt32 s_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,
scr_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_SCREEN,
0, IntPtr.Zero);
Marshal.FreeHGlobal(scr_conf);
NTSmartPublisherSDK.NT_PB_SetSleepMode(publisher_handle_, checkbox_black_screen_.Checked ? 1 : 0, 0);
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, UInt32.Parse(edit_frame_rate_.Text));
}
else if (btn_check_desktop_input_.Checked && !btn_check_scale_desktop_.Checked)
{
NTSmartPublisherSDK.NT_PB_SetScreenClip(publisher_handle_,
UInt32.Parse(edit_clip_left_.Text),
UInt32.Parse(edit_clip_top_.Text),
UInt32.Parse(edit_clip_width_.Text),
UInt32.Parse(edit_clip_height_.Text));
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, UInt32.Parse(edit_frame_rate_.Text));
}
else if (btn_check_window_input_.Checked)
{
if (IntPtr.Zero != cur_sel_capture_window_)
{
NTSmartPublisherSDK.NT_PB_SetCaptureWindow(publisher_handle_, cur_sel_capture_window_);
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, UInt32.Parse(edit_frame_rate_.Text));
NTSmartPublisherSDK.NT_PB_ClearLayersConfig(publisher_handle_, 0, 0, IntPtr.Zero);
}
}
else if (btn_check_camera_input_.Checked)
{
if (-1 != cur_sel_camera_index_
&& -1 != cur_sel_camera_resolutions_index_
&& -1 != cur_sel_camera_frame_rate_index_)
{
CameraInfo camera = cameras_[cur_sel_camera_index_];
NT_PB_VideoCaptureCapability cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
NTSmartPublisherSDK.NT_PB_SetVideoCaptureDeviceBaseParameter(publisher_handle_,
camera.id_.ToString(), (UInt32)cap.width_, (UInt32)cap.height_);
NTSmartPublisherSDK.NT_PB_SetFrameRate(publisher_handle_, (UInt32)(cur_sel_camera_frame_rate_index_ + 1));
if (btn_check_flip_vertical_camera_.Checked)
{
NTSmartPublisherSDK.NT_PB_FlipVerticalCamera(publisher_handle_, 1);
}
else
{
NTSmartPublisherSDK.NT_PB_FlipVerticalCamera(publisher_handle_, 0);
}
if (btn_check_flip_horizontal_camera_.Checked)
{
NTSmartPublisherSDK.NT_PB_FlipHorizontalCamera(publisher_handle_, 1);
}
else
{
NTSmartPublisherSDK.NT_PB_FlipHorizontalCamera(publisher_handle_, 0);
}
Int32 degress = GetCameraRotateDegress();
NTSmartPublisherSDK.NT_PB_RotateCamera(publisher_handle_, degress);
}
}
音视频参数设定
其他音视频相关接口参数设定,比是否启用DXGI, Aero模式,软硬编码模式,帧率关键帧间隔码率等设定。
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)
{
NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMax(publisher_handle_, Int32.Parse(edit_qp_max_.Text));
NTSmartPublisherSDK.NT_PB_SetVideoEncoderQPMin(publisher_handle_, Int32.Parse(edit_qp_min_.Text));
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));
}
获取视频码率默认值,不是每个开发者都有音视频开发背景,如果不想自行设置码率等一些参数,可参考我们的码率设定。
开始推送
设置推送URL后,调用StartPublisher接口开始推流,如需发送扩展SEI用户数据,推送之前设置下数据发送对接大小。
停止推送
调用NT_PB_StopPublisher()即可,停止推送后,如果没有录像等,可调用NT_PB_Close()接口,关掉实例,并把handle置 IntPtr.Zero。
预览推送数据
设置NT_PB_SetVideoPreviewImageCallBack(),调用NT_PB_StartPreview()接口即可。
停止预览更简单,调用NT_PB_StopPreview()。
实时截图
问答式参考
1视频采集设置
说明:
1. 屏幕和摄像头相互切换:用于在线教育或者无纸化等场景,推送或录像过程中,随时切换屏幕或摄像头数据(切换数据源),如需实时切换,点击页面“切换到摄像头”按钮即可;
2. 设置遮盖层,用于设定一个长方形或正方形区域(可自指定区域大小),遮盖不想给用户展示的部分;
3. 水印:添加PNG水印,支持推送或录像过程中,随时添加、取消水印;
4. 摄像头叠加到屏幕:意在用于同屏过程中,主讲人摄像头悬浮于屏幕之上(可指定叠加坐标),实现双画面展示,推送或录像过程中,可以随时取消摄像头叠加;
5. 屏幕叠加到摄像头:同4,效果展示,实际根据需求实现;
6. 采集桌面:可以通过点击“选择屏幕区域”获取采集区域,并可在采集过程中,随时切换区域位置,如不设定,默认全屏采集;
7. 使用DXGI采集屏幕,采集时停用Aero;
8. 采集窗口:可设定需要采集的窗口,窗口放大或缩小,推送端会自适应码率和分辨率;
9. 采集帧率(帧/秒):默认屏幕采集12帧,可根据实际场景需求设定到期望帧率;
10. 缩放屏幕大小缩放比:用于高清或超高清屏,通过设定一定的比例因子,缩放屏幕采集分辨率;
11. 采集摄像头:可选择需要采集的摄像头、采集分辨率、帧率、是否需要水平或者垂直反转、是否需要旋转;
追加提问:
问题[确认数据源]:采集桌面还是摄像头?如果桌面,全屏还是部分区域?
回答:
如果是摄像头:可以选择摄像头列表,然后分辨率、帧率。
如果是屏幕:默认帧率是12帧,可以根据实际场景调整,选取屏幕区域,可以实时拉取选择需要采集或录像区域;
如果是叠加模式:可选择摄像头叠加到屏幕,还是屏幕叠加到摄像头;
更高需求的用户,可以设置水印或应用层遮盖。
问题:如果是摄像头,采集到的摄像头角度不对怎么办?
回答:我们支持摄像头镜像和翻转设置,摄像头可通过SDK接口轻松实现水平/垂直翻转、镜像效果。
2 视频码率控制
如何选择适合我的码率?
回答:如果不是有音视频背景的开发人员,可点击“获取视频码率默认值”,参考我们默认的码率推荐,如果觉得推荐码率过高或不够,可根据实际情况酌情调整。
265编码还是H.264编码?
回答:Windows平台支持H.265特定机型硬编码,如果推RTMP流,需要服务器支持RTMP H.265扩展,播放器SDK,也需要同步支持RTMP H.265扩展播放。
如果是轻量级RTSP服务SDK对接的话,只需要播放器支持RTSP H.265即可。
如果推摄像头数据,建议采用可变码率+H.265编码。
如何设置码率参数更合理?
回答:
关键帧间隔:一般来说,设置到帧率的2-4倍,比如帧率20,关键帧间隔可以设置到40-80;
平均码率:可以点击“获取视频码率默认值”,最大码率是平均码率的2倍;
视频质量:如果使用可变码率,建议采用大牛直播SDK默认推荐视频质量值;
编码速度:如高分辨率,建议1-3,值越小,编码速度越快;
H.264 Profile:默认baseline profile,可根据需要,酌情设置High profile;
NOTE:点击“推送”或“录像”或启动内置RTSP服务SDK之前,请务必设置视频码率,如不想手动设置,请点击“获取视频码率默认值”!!!
3 音频采集设置
问答式:采集音频吗?如果采集,采集麦克风还是扬声器的,亦或混音?
回答:
如果想采集电脑输出的音频(比如音乐之类),可以选择“采集扬声器”;
如果想采集麦克风音频,可以选择“采集麦克风”,并选择相关设备;
如果两个都想采集,可以两个都选择,混音输出。
4 实时音量调节
问答式:采集过程中可以改变麦克风或扬声器采集音量吗?
回答:可以,如果二者都选中,处于混音模式,也可单独调整麦克风或扬声器音量。
5 音频编码
问题:是AAC还是SPEEX?
回答:我们默认是AAC编码模式,如果需要码率更低,可以选择SPEEX编码模式,当然我们的AAC编码码率也不高,如果没有太高要求,考虑到通用性,建议使用AAC。
6 音频处理
问题:我想过滤背景噪音怎么办?
回答:选中“噪音抑制”,“噪音抑制“请和“自动增益控制”组合使用,“端点检测(VAD)”可选设置。
问题:我想做一对一互动怎么办?
回答:选中“回音消除”,可以和“噪音抑制”、“自动增益控制”组合使用,具体可参看回音消除的demo工程:WIN-EchoCancellation-CSharp-Demo。
问题:我推送或者录像过程中,随时静音怎么办?
回答:推送过程中,随时选择或取消选择“静音”功能。
7多路推送
问题:我想同时推送到多个url怎么办(比如一个内网服务器,一个外网服务器)?
回答:同时填写多个url(最多3个),然后点推送即可。
8 截图(快照)
问题:我想推送或者录像过程中,截取当前图像怎么办?
回答:那就设置好截图路径,推送或录像过程中,随时点击“截图”。
9 录像
问题:我还想录像,怎么办?
回答:设置录像文件存放目录,文件前缀、单个文件大小,是否加日期、时间,随时录制即可,此外,我们的SDK还支持录像过程中,暂停录像,恢复录像。
10 实时预览
问题:我还想看看推出去视频,特别是合成后的效果,怎么办?
回答:点击页面的“预览”按钮,就可以看到。