批量做网站,网站代维护,什么网站可以做兼职设计,威海网络科技有限公司我们在做RTSP、RTMP播放器的时候#xff0c;遇到这样的诉求#xff1a;特别是RTSP#xff0c;有些摄像头安装可能倒置或者旋转了90亦或270#xff0c;拉取到图像#xff0c;势必需要对视频图像做一定的处理#xff0c;确保显示正常。
为此#xff0c;我们提供了以下接口…我们在做RTSP、RTMP播放器的时候遇到这样的诉求特别是RTSP有些摄像头安装可能倒置或者旋转了90°亦或270°拉取到图像势必需要对视频图像做一定的处理确保显示正常。
为此我们提供了以下接口视频数据水平反转、垂直反转、设置旋转角度。
好多开发者搞不清楚特别是水平反转和垂直反转以下我们以图例的形式做个效果展示。
先看原始图像 水平反转后 垂直反转后 按照设定角度旋转90°、180°、270° 以C的接口为例设计如下
/**上下反转(垂直反转)*is_flip: 1:表示反转, 0:表示不反转*/NT_UINT32(NT_API *SetFlipVertical)(NT_HANDLE handle, NT_INT32 is_flip);/**水平反转*is_flip: 1:表示反转, 0:表示不反转*/NT_UINT32(NT_API *SetFlipHorizontal)(NT_HANDLE handle, NT_INT32 is_flip);/*设置旋转顺时针旋转degress 设置0 90 180 270度有效其他值无效注意除了0度其他角度播放会耗费更多CPU接口调用成功返回NT_ERC_OK*/NT_UINT32(NT_API* SetRotation)(NT_HANDLE handle, NT_INT32 degress);
以上接口设计考虑到图像出来后才可以知道要怎么调整设计成了可实时调用的接口模式。
具体调用逻辑非常简单
player_api_.SetFlipVertical(player_handle_, BST_CHECKED btn_check_flip_vertical_.GetCheck() ? 1 :0 );player_api_.SetFlipHorizontal(player_handle_, BST_CHECKED btn_check_flip_horizontal_.GetCheck() ? 1 : 0);player_api_.SetRotation(player_handle_, rotate_degrees_);
旋转角度按钮逻辑
void CSmartPlayerDlg::OnBnClickedButtonRotation()
{rotate_degrees_ 90;rotate_degrees_ rotate_degrees_ % 360;if (0 rotate_degrees_){btn_rotation_.SetWindowText(_T(旋转90度));}else if (90 rotate_degrees_){btn_rotation_.SetWindowText(_T(旋转180度));}else if (180 rotate_degrees_){btn_rotation_.SetWindowText(_T(旋转270度));}else if (270 rotate_degrees_){btn_rotation_.SetWindowText(_T(不旋转));}if ( player_handle_ ! NULL ){player_api_.SetRotation(player_handle_, rotate_degrees_);}
}
总的来说实现难度不大此外我们针对视频数据还设计了只解关键帧、按照视频宽高scale显示图像最大限度的方便用户使用。
/**设置只解码视频关键帧*is_only_dec_key_frame: 1:表示只解码关键帧, 0:表示都解码, 默认是0*成功返回NT_ERC_OK*/NT_UINT32(NT_API *SetOnlyDecodeVideoKeyFrame)(NT_HANDLE handle, NT_INT32 is_only_dec_key_frame);
/*设置视频画面的填充模式如填充整个绘制窗口、等比例填充绘制窗口如不设置默认填充整个绘制窗口handle: 播放句柄mode 0: 填充整个绘制窗口; 1: 等比例填充绘制窗口, 默认值是0成功返回NT_ERC_OK*/NT_UINT32 (NT_API *SetRenderScaleMode)(NT_HANDLE handle, NT_INT32 mode);
如果以上数据都还不满足开发者或终端用户的需求我们还可以把数据YUV/RGB回调上来用户自行处理。
player_api_.SetVideoFrameCallBack(player_handle_, NT_SP_E_VIDEO_FRAME_FORMAT_RGB32,GetSafeHwnd(), SM_SDKVideoFrameHandle);
extern C NT_VOID NT_CALLBACK SM_SDKVideoFrameHandle(NT_HANDLE handle, NT_PVOID userData, NT_UINT32 status,const NT_SP_VideoFrame* frame)
{/*if (frame ! NULL){std::ostringstream ss;ss Receive frame time_stamp: frame-timestamp_ ms \r\n;OutputDebugStringA(ss.str().c_str());}*/if ( frame ! NULL ){if ( NT_SP_E_VIDEO_FRAME_FORMAT_RGB32 frame-format_ frame-plane0_ ! NULL frame-stride0_ 0 frame-height_ 0 ){std::unique_ptrnt_rgb32_image pImage(new nt_rgb32_image());pImage-size_ frame-stride0_* frame-height_;pImage-data_ new NT_BYTE[pImage-size_];memcpy(pImage-data_, frame-plane0_, pImage-size_);pImage-width_ frame-width_;pImage-height_ frame-height_;pImage-stride_ frame-stride0_;HWND hwnd (HWND)userData;if ( hwnd ! NULL ::IsWindow(hwnd) ){::PostMessage(hwnd, WM_USER_SDK_RGB32_IMAGE, (WPARAM)handle, (LPARAM)pImage.release());}}}
}
有了这些数据接口的加持播放端对数据处理非常方便。