【教程】RTSP/GB28181/HIKSDK/Ehome協議視頻平臺EasyCVR,如何經過ffmpeg 將 H.264 I幀數據轉換爲 BGR 數據?

EasyCVR做爲視頻融合平臺,可以支持除RTMP之外的大部分協議,包括海康SDK及Ehome私有協議,視頻雲網關不須要對現有監控架構作調整,支持CDN推流,靈活適應原有架構。算法

EasyCVR.png

在 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視頻上雲網關

EasyCVR1.png

  • 多終端兼容
    支持傳統網絡攝像機、NVR、編碼器、SDK等設備,最大程度的提升了硬件設備的兼容性;
  • 靈活擴展
    按需靈活擴展、收縮資源,免去了插件安裝、瀏覽器限定等條件,實現了無插件、多平臺自由觀看回放;
  • 快速接入雲端
    支持阿里雲、騰訊雲、華爲雲、七牛雲等,支持S3和Swift接口的對象存儲服務,簡單配置,部署更高效。

若是你們還想了解更多關於EasyCVR相關內容,或有視頻相關需求,歡迎在博客下方留言,聯繫咱們。編碼

相關文章
相關標籤/搜索