• RTSP/GB28181/HIKSDK/Ehome协议视频平台EasyCVR如何通过ffmpeg 将 H.264 I帧数据转换为 BGR 数据?


    EasyCVR作为视频融合平台,能够支持除RTMP以外的大部分协议,包括海康SDK及Ehome私有协议,视频云网关不需要对现有监控架构做调整,支持CDN推流,灵活适应原有架构。

    在 EasyCVR 视频处理中,对于部分视频数据需要转换成 BGR 数据才能够使用。

    I 帧数据为采用视频压缩算法已经压缩后的数据。数据量小,便于存储和传输。在正式使用时,如播放视频等功能,都需要重新将压缩后的数据还原成YUV 或者 RGB 等模型的程序才可以显示使用。

    BGR 数据为和 RGB 相同的数据,仅是顺序不同,RGB 数据时红色、绿色和蓝色的顺序,BGR 是蓝色、绿色和红色的顺序模型。

    使用 ffmpeg 代码将 H.264 一帧数据转换成 BGR 数据的功能代码如下。因为 ffmpeg 的代码在 3.x 后,部分接口进行了修改,以下代码在 ffmpeg4.2 中可正常运行。

    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/avutil.h>
    #include <libavutil/imgutils.h>
    #include <libswscale/swscale.h>
    // 将 H.264 帧转换为 BGR 数据
    void H264ToBGR(char* data, int dataSize, char* outBuffer) {
    	// 1. 将元数据装填到packet
    	AVPacket* avPkt = av_packet_alloc();
    	avPkt->size = dataSize;
    	avPkt->data = (unsigned char*)data;
    	static AVCodecContext* codecCtx = nullptr;
    	// 2. 创建并配置codecContext
    	if (codecCtx == nullptr) {
    		AVCodec* h264Codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    		codecCtx = avcodec_alloc_context3(h264Codec);
    		avcodec_get_context_defaults3(codecCtx, h264Codec);
    		avcodec_open2(codecCtx, h264Codec, nullptr);
    	}
    	// 3. 解码
    	auto ret = avcodec_send_packet(codecCtx, avPkt);
    	if (ret >= 0) {
    		AVFrame* YUVFrame = av_frame_alloc();
    		ret = avcodec_receive_frame(codecCtx, YUVFrame);
    		if (ret >= 0) {
    			// 4.YUV转BGR24
    			AVFrame* RGB24Frame = av_frame_alloc();
    			AVPixelFormat yuvFmt = convertDeprecatedFormat(codecCtx->pix_fmt);
    			struct SwsContext* convertCxt = sws_getContext(
    				YUVFrame->width, YUVFrame->height, yuvFmt,
    				YUVFrame->width, YUVFrame->height, AV_PIX_FMT_BGR24,
    				SWS_POINT, NULL, NULL, NULL);
    			printf("yuv 数据的编码格式为 %d\n", yuvFmt);
    			// outBuffer将会分配给RGB24Frame->data,AV_PIX_FMT_RGB24格式只分配到RGB24Frame->data[0]
    			av_image_fill_arrays(RGB24Frame->data, RGB24Frame->linesize, (unsigned char*)outBuffer,
    				AV_PIX_FMT_BGR24, YUVFrame->width, YUVFrame->height, 1);
    			sws_scale(convertCxt, YUVFrame->data, YUVFrame->linesize, 0, YUVFrame->height, RGB24Frame->data, RGB24Frame->linesize);
    			// 5.清除各对象/context -> 释放内存
    			// free context and avFrame
    			sws_freeContext(convertCxt);
    			av_frame_free(&RGB24Frame);             // RGB24Frame.
    		}
    		// free context and avFrame
    		av_frame_free(&YUVFrame);
    	}
    	// free context and avFrame
    	av_packet_unref(avPkt);
    	av_packet_free(&avPkt);
    	avcodec_free_context(&codecCtx);
    }
    
    
    // 把已经废除的格式转换成新的格式,防止报 "deprecated pixel format used, make sure you did set range correctly" 错误
    AVPixelFormat convertDeprecatedFormat(enum AVPixelFormat format)
    {
    	switch (format)
    	{
    	case AV_PIX_FMT_YUVJ420P:
    		return AV_PIX_FMT_YUV420P;
    		break;
    	case AV_PIX_FMT_YUVJ422P:
    		return AV_PIX_FMT_YUV422P;
    		break;
    	case AV_PIX_FMT_YUVJ444P:
    		return AV_PIX_FMT_YUV444P;
    		break;
    	case AV_PIX_FMT_YUVJ440P:
    		return AV_PIX_FMT_YUV440P;
    		break;
    	default:
    		return format;
    		break;
    	}
    }
    
    

    在上述代码中convertDeprecatedFormat主要是转换格式的函数。随着 ffmpeg 程序的升级,很多原有的代码不再建议使用,如果想兼容原有的程序需要做一些处理,否则程序中就会报 warning 警告,虽然不影响使用,但是消除 warning 代码结构会更清晰。

    关于EasyCVR视频上云网关

    • 多终端兼容
      支持传统网络摄像机、NVR、编码器、SDK等设备,最大程度的提高了硬件设备的兼容性;
    • 灵活扩展
      按需灵活扩展、收缩资源,免去了插件安装、浏览器限定等条件,实现了无插件、多平台自由观看回放;
    • 快速接入云端
      支持阿里云、腾讯云、华为云、七牛云等,支持S3和Swift接口的对象存储服务,简单配置,部署更高效。

    如果大家还想了解更多关于EasyCVR相关内容,或有视频相关需求,欢迎在博客下方留言,联系我们。

  • 相关阅读:
    OCP-1Z0-051-V9.02-118题
    VC++ 获取临时目录
    VC++ UUID/GUID
    MFC无边框的窗体实现用鼠标拖动窗体边缘实现窗体大小变化
    Win32 SDK程序中拖动Thin边框窗口来改变窗口大小
    HTML5 App实战(7):连连看
    MFC对话框Border类型(None、Thin、Resizing、Dialog Frame)对应的部分属性
    项目报错七
    Linux下如何查看高CPU占用率线程
    项目报错六
  • 原文地址:https://www.cnblogs.com/TSINGSEE/p/13809631.html
Copyright © 2020-2023  润新知