视音频数据处理入门:颜色空间(二)---ffmpeg

news2025/3/6 9:03:45

目录

概述

流程

相关流程

初始化方法

初始化代码

转换方法

转换代码

释放方法

整体代码介绍

代码路径


概述

本篇简单说一下基于FFmpeg的libswscale的颜色空间转换;Libswscale里面实现了各种图像像素格式的转换,例如:YUV与RGB之间的转换等;这里简单说以下Libswscale的颜色空间转换的使用方法。

流程

相关流程

Libswscale使用起来很方便,最主要的函数只有3个:
(1)       sws_getContext():使用参数初始化SwsContext结构体。
(2)       sws_scale():转换一帧图像。
(3)       sws_freeContext():释放SwsContext结构体。
其中sws_getContext()也可以用另一个接口函数sws_getCachedContext()取代。

初始化方法

初始化SwsContext我们这里选用sws_getContext();除了上述函数之外还有另一种方法,更加灵活,可以配置更多的参数。该方法调用的函数如下所示:
1)  sws_alloc_context():为SwsContext结构体分配内存。
2)  av_opt_set_XXX():通过av_opt_set_int(),av_opt_set()…等等一系列方法设置SwsContext结构体的值。在这里需要注意,SwsContext结构体的定义看不到,所以不能对其中的成员变量直接进行赋值,必须通过av_opt_set()这类的API才能对其进行赋值。
3)  sws_init_context():初始化SwsContext结构体。
与第一种方式相比这种复杂的方法可以配置一些sws_getContext()配置不了的参数。比如说设置图像的YUV像素的取值范围是JPEG标准(Y、U、V取值范围都是0-255)还是MPEG标准(Y取值范围是16-235,U、V的取值范围是16-240)。

初始化代码

m_imgConvertCtx = sws_getContext(cfg->srcWide, cfg->srcHigh, srcIter->second,
		cfg->dstWide, cfg->dstHigh, dstIter->second, SWS_BICUBIC, NULL, NULL, NULL);

转换方法

对于转换函数就没有特别说明的了调用sws_scale();值得注意就是这个函数的参数的传递需要按照对应的颜色空间进行排列;

转换代码

sws_scale(m_imgConvertCtx, m_srcPointers, m_srcLinesizes, 0, m_srcHigh, m_dstPointers, m_dstLinesizes);

释放方法


	if (nullptr != m_imgConvertCtx)
	{
		sws_freeContext(m_imgConvertCtx);
	}

	m_imgConvertCtx = nullptr;

整体代码介绍

对应FFmpeg 颜色空间转换的demo这边封装成了一个类函数,主要提供了  NV12、NV21、YUV420P、YUV422P、RGB24、RGBA相互转换功能。如需扩展则实现对应函数即可。

头文件:ColorConversionFFmpeg.h

/**
 * FFmpeg的颜色空间转换
 * YUV Transformation
 *
 * 梁启东 qidong.liang
 * 18088708700@163.com
 * https://blog.csdn.net/u011645307
 *
 *
 * 本程序实现了FFmpeg的YUV数据之间的转换和YUV与RGB的转换。
 * 提供了如下:
 * 	FFMPEG_AV_PIX_FMT_NOKNOW,
 *	FFMPEG_AV_PIX_FMT_NV12,
 *	FFMPEG_AV_PIX_FMT_NV21,
 *	FFMPEG_AV_PIX_FMT_YUV420P,
 *	FFMPEG_AV_PIX_FMT_YUV422P,
 *	FFMPEG_AV_PIX_FMT_RGB24,
 *	FFMPEG_AV_PIX_FMT_RGBA
 *  相互转换功能
 */
#ifndef COLOR_CONVERSION_FFMPEG_H
#define	COLOR_CONVERSION_FFMPEG_H

#ifdef _WIN32
//Windows
extern "C"
{
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#ifdef __cplusplus
};
#endif
#endif

#include <map>
#include <functional>

#ifndef FFMPEG_PIX_FORMAT
#define	FFMPEG_PIX_FORMAT
typedef enum FFmpegAVPixelFormat
{
	FFMPEG_AV_PIX_FMT_NOKNOW,
	FFMPEG_AV_PIX_FMT_NV12,
	FFMPEG_AV_PIX_FMT_NV21,
	FFMPEG_AV_PIX_FMT_YUV420P,
	FFMPEG_AV_PIX_FMT_YUV422P,
	FFMPEG_AV_PIX_FMT_RGB24,
	FFMPEG_AV_PIX_FMT_RGBA

}FFmpegAVPixelFormat;

#endif//FFMPEG_PIX_FORMAT
#ifndef FFMPEG_SCALE_CONFIG
#define	FFMPEG_SCALE_CONFIG
typedef struct FFmpegSwscaleConfig
{
	unsigned int srcWide;
	unsigned int srcHigh;
	FFmpegAVPixelFormat srcFormat;
	unsigned int dstWide;
	unsigned int dstHigh;
	FFmpegAVPixelFormat dstFormat;

	FFmpegSwscaleConfig()
	{
		srcWide = 0;
		srcHigh = 0;
		srcFormat = FFMPEG_AV_PIX_FMT_NOKNOW;
		dstWide = 0;
		dstHigh = 0;
		dstFormat = FFMPEG_AV_PIX_FMT_NOKNOW;
	}
}FFmpegSwscaleConfig;
#endif // !FFMPEG_SCALE_CONFIG

class ColorConversionFFmpeg
{
public:
	ColorConversionFFmpeg();
	~ColorConversionFFmpeg();

	long Init(FFmpegSwscaleConfig* cfg);
	long Conversion(const char* inputBuff, char* outputBuff);
	long UnInit();

private:
	long BuffToAVPixFmtYUV420P(char* inputBuff, unsigned char** pixBuff);
	long BuffToAVPixFmtRGBA(char* inputBuff, unsigned char** pixBuff);
	long BuffToAVPixFmtRGB24(char* inputBuff, unsigned char** pixBuff);
	long BuffToAVPixFmtNV12(char* inputBuff, unsigned char** pixBuff);
	long BuffToAVPixFmtNV21(char* inputBuff, unsigned char** pixBuff);
	long BuffToAVPixFmtYUV422P(char* inputBuff, unsigned char** pixBuff);

	long AVPixFmtYUV420PToBuff(unsigned char** pixBuff, char* outputBuff);
	long AVPixFmtNV12ToBuff(unsigned char** pixBuff, char* outputBuff);
	long AVPixFmtNV21ToBuff(unsigned char** pixBuff, char* outputBuff);
	long AVPixFmtYUV422PToBuff(unsigned char** pixBuff, char* outputBuff);
	long AVPixFmtRGB24ToBuff(unsigned char** pixBuff, char* outputBuff);
	long AVPixFmtRGBAToBuff(unsigned char** pixBuff, char* outputBuff);

private:
	SwsContext* m_imgConvertCtx;
	uint8_t* m_srcPointers[4]{ nullptr,nullptr,nullptr,nullptr };
	int m_srcLinesizes[4]{0,0,0,0};
	uint8_t* m_dstPointers[4]{ nullptr,nullptr,nullptr,nullptr };
	int m_dstLinesizes[4]{ 0,0,0,0 };

	int m_srcHigh;
	int m_srcWide;
	std::function < long(char* inputBuff, unsigned char** pixBuff) > m_infun;
	std::function < long(unsigned char** pixBuff, char* outputBuff) > m_outfun;
	std::map<FFmpegAVPixelFormat, AVPixelFormat>			m_PixelFormatMap;
	std::map<FFmpegAVPixelFormat,
		std::function < long(
			char* inputBuff,
			unsigned char** pixBuff) >>					    m_srcFormatFunMap;
	std::map<FFmpegAVPixelFormat,
		std::function < long(
			unsigned char** pixBuff,
			char* outputBuff) >>						    m_dstFormatFunMap;
};
#endif//COLOR_CONVERSION_FFMPEG_H

源文件:ColorConversionFFmpeg.cpp

#include "ColorConversionFFmpeg.h"

ColorConversionFFmpeg::ColorConversionFFmpeg()
	: m_imgConvertCtx(nullptr)
	, m_infun(nullptr)
	, m_outfun(nullptr)
	, m_srcHigh(0)
	, m_srcWide(0)
{

	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_NV12, AV_PIX_FMT_NV12));
	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_NV21, AV_PIX_FMT_NV21));
	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P));
	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P));
	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB24));
	m_PixelFormatMap.insert(std::pair<FFmpegAVPixelFormat, AVPixelFormat>(FFMPEG_AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA));

	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_NV12] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtNV12,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_NV21] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtNV21,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_YUV420P] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtYUV420P,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_YUV422P] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtYUV422P,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_RGB24] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtRGB24,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_srcFormatFunMap[FFMPEG_AV_PIX_FMT_RGBA] = std::bind(&ColorConversionFFmpeg::BuffToAVPixFmtRGBA,
		this,
		std::placeholders::_1,
		std::placeholders::_2);


	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_NV12] = std::bind(&ColorConversionFFmpeg::AVPixFmtNV12ToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_NV21] = std::bind(&ColorConversionFFmpeg::AVPixFmtNV21ToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_YUV420P] = std::bind(&ColorConversionFFmpeg::AVPixFmtYUV420PToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_YUV422P] = std::bind(&ColorConversionFFmpeg::AVPixFmtYUV422PToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_RGB24] = std::bind(&ColorConversionFFmpeg::AVPixFmtRGB24ToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);
	m_dstFormatFunMap[FFMPEG_AV_PIX_FMT_RGBA] = std::bind(&ColorConversionFFmpeg::AVPixFmtRGBAToBuff,
		this,
		std::placeholders::_1,
		std::placeholders::_2);

}

ColorConversionFFmpeg::~ColorConversionFFmpeg()
{
	m_PixelFormatMap.clear();
	m_srcFormatFunMap.clear();
	m_dstFormatFunMap.clear();

}

long ColorConversionFFmpeg::Init(FFmpegSwscaleConfig* cfg)
{
	if (nullptr == cfg)
	{
		return -1;
	}
	auto srcIter = m_PixelFormatMap.find(cfg->srcFormat);
	auto dstIter = m_PixelFormatMap.find(cfg->dstFormat);
	if (srcIter == m_PixelFormatMap.end() ||
		dstIter == m_PixelFormatMap.end())
	{
		return -2;
	}
	auto srcFormatFunIter = m_srcFormatFunMap.find(cfg->srcFormat);
	auto dstFormatFunIter = m_dstFormatFunMap.find(cfg->dstFormat);
	if (dstFormatFunIter == m_dstFormatFunMap.end() ||
		srcFormatFunIter == m_srcFormatFunMap.end())
	{
		return -3;
	}

	m_infun = srcFormatFunIter->second;
	m_outfun = dstFormatFunIter->second;

	int nSrctBuffLen = 0, nDstBuffLen = 0;

	nSrctBuffLen = av_image_alloc(m_srcPointers, m_srcLinesizes, cfg->srcWide, cfg->srcHigh, srcIter->second, 1);
	if (nSrctBuffLen <= 0)
	{
		return -4;
	}
	nDstBuffLen = av_image_alloc(m_dstPointers, m_dstLinesizes, cfg->dstWide, cfg->dstHigh, dstIter->second, 1);
	if (nDstBuffLen <= 0 )
	{
		av_freep(&m_srcPointers[0]);
		return -5;
	}

	m_imgConvertCtx = sws_getContext(cfg->srcWide, cfg->srcHigh, srcIter->second,
		cfg->dstWide, cfg->dstHigh, dstIter->second, SWS_BICUBIC, NULL, NULL, NULL);
	
	if (nullptr == m_imgConvertCtx)
	{
		av_freep(&m_srcPointers);
		av_freep(&m_dstPointers);
		return -6;
	}

	m_srcHigh = cfg->srcHigh;
	m_srcWide = cfg->srcWide;

	return 0;
}

long ColorConversionFFmpeg::Conversion(const char* inputBuff, char* outputBuff)
{
	if (nullptr == m_infun ||
		nullptr == m_outfun ||
		nullptr == m_dstPointers[0] ||
		nullptr == m_srcPointers[0] ||
		nullptr == m_imgConvertCtx)
	{
		return 0;
	}
	
	m_infun(const_cast<char*>(inputBuff), m_srcPointers);

	sws_scale(m_imgConvertCtx, m_srcPointers, m_srcLinesizes, 0, m_srcHigh, m_dstPointers, m_dstLinesizes);

	m_outfun(m_dstPointers, outputBuff);
	return 0;
}

long ColorConversionFFmpeg::UnInit()
{
	if (m_srcPointers)
	{
		av_freep(&m_srcPointers);
	}
	if (m_dstPointers)
	{
		av_freep(&m_dstPointers);
	}

	m_dstPointers[0] = nullptr;
	m_srcPointers[0] = nullptr;

	if (nullptr != m_imgConvertCtx)
	{
		sws_freeContext(m_imgConvertCtx);
	}

	m_imgConvertCtx = nullptr;
	m_outfun = nullptr;
	m_infun = nullptr;

	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtYUV420P(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, static_cast<size_t>(m_srcWide * m_srcHigh));											//Y
	memcpy(pixBuff[1], inputBuff + m_srcWide * m_srcHigh, m_srcWide * m_srcHigh / 4);				//U
	memcpy(pixBuff[2], inputBuff + m_srcWide * m_srcHigh * 5 / 4, m_srcWide * m_srcHigh / 4);		//V
	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtRGBA(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, m_srcWide * m_srcHigh*4);
	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtRGB24(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, m_srcWide * m_srcHigh * 3);
	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtNV12(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, m_srcHigh*m_srcWide);                    //Y
	memcpy(pixBuff[1], inputBuff + m_srcHigh * m_srcWide, m_srcHigh*m_srcWide / 2);      //Uv
	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtNV21(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, m_srcHigh * m_srcWide);                    //Y
	memcpy(pixBuff[1], inputBuff + m_srcHigh * m_srcWide, m_srcHigh * m_srcWide / 2);      //Uv
	return 0;
}

long ColorConversionFFmpeg::BuffToAVPixFmtYUV422P(char* inputBuff, unsigned char** pixBuff)
{
	memcpy(pixBuff[0], inputBuff, m_srcWide * m_srcHigh);											//Y
	memcpy(pixBuff[1], inputBuff + m_srcWide * m_srcHigh, m_srcWide * m_srcHigh / 2);				//U
	memcpy(pixBuff[2], inputBuff + m_srcWide * m_srcHigh * 3 / 2, m_srcWide * m_srcHigh / 2);		//V
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtYUV420PToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy(outputBuff, pixBuff[0], m_srcWide * m_srcHigh);											//Y
	memcpy(outputBuff + m_srcWide * m_srcHigh, pixBuff[1], m_srcWide * m_srcHigh / 4);				//U
	memcpy(outputBuff + m_srcWide * m_srcHigh * 5 / 4, pixBuff[2], m_srcWide * m_srcHigh / 4);		//V
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtNV12ToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy( outputBuff, pixBuff[0], m_srcHigh * m_srcWide);                    //Y
	memcpy( outputBuff + m_srcHigh * m_srcWide, pixBuff[1], m_srcHigh * m_srcWide / 2);      //Uv
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtNV21ToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy(outputBuff, pixBuff[0], m_srcHigh * m_srcWide);                    //Y
	memcpy(outputBuff + m_srcHigh * m_srcWide, pixBuff[1], m_srcHigh * m_srcWide / 2);      //Uv
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtYUV422PToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy(outputBuff, pixBuff[0], m_srcWide * m_srcHigh);											//Y
	memcpy(outputBuff + m_srcWide * m_srcHigh, pixBuff[1], m_srcWide * m_srcHigh / 2);				//U
	memcpy(outputBuff + m_srcWide * m_srcHigh * 3 / 2, pixBuff[2], m_srcWide * m_srcHigh / 2);		//V
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtRGB24ToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy(outputBuff, pixBuff[0], m_srcWide * m_srcHigh * 3);
	return 0;
}

long ColorConversionFFmpeg::AVPixFmtRGBAToBuff(unsigned char** pixBuff, char* outputBuff)
{
	memcpy(outputBuff, pixBuff[0], m_srcWide * m_srcHigh * 4);
	return 0;
}

测试文件:main.cpp

/**
* FFmpeg的颜色空间转换的测试程序
* YUV Transformation
*
* 梁启东 qidong.liang
* 18088708700@163.com
* https://blog.csdn.net/u011645307
*
*
* FFmpeg的颜色空间转换的测试程序
*/

#include <iostream>
#include "ColorConversionFFmpeg.h"


#define NV12_To_I420	0
#define I420_To_NV12	0
#define NV21_To_I420	0
#define I420_To_NV21	0
#define I420_To_RGB32	0
#define RGB32_To_I420	0
#define I420_To_RGB24	0
#define RGB24_To_I420	0
#define NV12_To_YUV422P	0
#define YUV422P_To_NV12	1
int main()
{
	FILE* file_in = nullptr;
	FILE* file_out = nullptr;
	char* input_name = nullptr;
	char* output_name = nullptr;

	int w = 0, h = 0;
	float flotScale = 0;
	int out_w = 0, out_h = 0;
	float out_flotScale = 0;

	FFmpegSwscaleConfig cfg;
	ColorConversionFFmpeg obj;

#if NV12_To_YUV422P
	input_name = const_cast<char*>("../in/nv21_480x272.yuv");
	output_name = const_cast<char*>("../out/yuvv422p_480x272.yuv");

	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_NV12;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_YUV422P;

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 2;

#endif

#if YUV422P_To_NV12

	input_name = const_cast<char*>("../in/YV16(422)_480x272.yuv");
	output_name = const_cast<char*>("../out/nv21_480x272.yuv");
	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_YUV422P;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_NV12;

	w = 480;
	h = 272;
	flotScale = 2;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

#endif

#if NV21_To_I420
	input_name = const_cast<char*>("../in/nv21_480x272.yuv");
	output_name = const_cast<char*>("../out/I420_480x272.yuv");

	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_NV21;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_YUV420P;

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

#endif

#if I420_To_NV21

	input_name = const_cast<char*>("../in/I420_480x272.yuv");
	output_name = const_cast<char*>("../out/nv21_480x272.yuv");
	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_NV21;

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

#endif

#if NV12_To_I420
	input_name = const_cast<char*>("../in/nv12_480x272.yuv");
	output_name = const_cast<char*>("../out/I420_480x272.yuv");

	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_NV12;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_YUV420P;

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

#endif

#if I420_To_NV12

	input_name = const_cast<char*>("../in/I420_480x272.yuv");
	output_name = const_cast<char*>("../out/nv12_480x272.yuv");
	cfg.srcWide = 480;
	cfg.dstWide = 480;
	cfg.dstHigh = 272;
	cfg.srcHigh = 272;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_NV12;

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

#endif

#if I420_To_RGB24
	input_name = const_cast<char*>("../in/I420_480x272.yuv");
	output_name = const_cast<char*>("../out/rgb_480x272.rgb");

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 3;

	cfg.srcWide = w;
	cfg.dstWide = out_w;
	cfg.dstHigh = out_h;
	cfg.srcHigh = h;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_RGB24;


#endif

#if RGB24_To_I420
	input_name = const_cast<char*>("../in/rgb_480x272.rgb");
	output_name = const_cast<char*>("../out/I420_480x272.yuv");

	w = 480;
	h = 272;
	flotScale = 3;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

	cfg.srcWide = w;
	cfg.dstWide = out_w;
	cfg.dstHigh = out_h;
	cfg.srcHigh = h;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_RGB24;

#endif

#if I420_To_RGB32
	input_name = const_cast<char*>("../in/I420_480x272.yuv");
	output_name = const_cast<char*>("../out/rgba_480x272.rgb");

	w = 480;
	h = 272;
	flotScale = 1.5;
	out_w = 480;
	out_h = 272;
	out_flotScale = 4;

	cfg.srcWide = w;
	cfg.dstWide = out_w;
	cfg.dstHigh = out_h;
	cfg.srcHigh = h;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_RGBA;

#endif

#if RGB32_To_I420
	input_name = const_cast<char*>("../in/rgba_480x272.rgb");
	output_name = const_cast<char*>("../out/I420_480x272.yuv");

	w = 480;
	h = 272;
	flotScale = 4;
	out_w = 480;
	out_h = 272;
	out_flotScale = 1.5;

	cfg.srcWide = w;
	cfg.dstWide = out_w;
	cfg.dstHigh = out_h;
	cfg.srcHigh = h;
	cfg.dstFormat = FFMPEG_AV_PIX_FMT_YUV420P;
	cfg.srcFormat = FFMPEG_AV_PIX_FMT_RGBA;

#endif

	int in_buff_len = w * h * flotScale;
	int out_buff_len = out_w * out_h * out_flotScale;
	char* inbuff = new char[in_buff_len];
	char* outbuff = new char[out_buff_len];
	fopen_s(&file_in, input_name, "rb+");
	fopen_s(&file_out, output_name, "wb+");


	int ret = obj.Init(&cfg);
	if (0 != ret)
	{
		printf("ColorConversionFFmpeg::Init ret:%d\n", ret);
		fclose(file_in);
		fclose(file_out);
		file_in = nullptr;
		file_out = nullptr;
		return -1;
	}
	while (true)
	{
		if (fread(inbuff, 1, in_buff_len, file_in) != in_buff_len)
		{
			break;
		}

		ret = obj.Conversion(inbuff, outbuff);
		if (0 != ret)
		{
			printf("ColorConversionFFmpeg::Conversion ret:%d\n", ret);
			continue;
		}
		fwrite(outbuff, 1, out_buff_len, file_out);
	}
	ret = obj.UnInit();
	if (0 != ret)
	{
		printf("ColorConversionFFmpeg::UnInit ret:%d\n", ret);
	}
	fclose(file_in);
	fclose(file_out);
	file_in = nullptr;
	file_out = nullptr;


    std::cout << "Hello World!\n";
}

代码路径

csdn:https://download.csdn.net/download/u011645307/21739481?spm=1001.2014.3001.5501

github:https://github.com/liangqidong/ColorConversion.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2310463.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

240 Vocabulary Words Kids Need to Know

《240 Vocabulary Words Kids Need to Know》是美国学乐出版社&#xff08;Scholastic&#xff09;推出的词汇学习系列练习册&#xff0c;专为美国小学阶段&#xff08;G1-G6&#xff09;设计&#xff0c;基于CCSS&#xff08;美国共同核心州立标准&#xff09;编写&#xff0c…

AI-Deepseek + PPT

01--Deepseek提问 首先去Deepseek问一个问题&#xff1a; Deepseek的回答&#xff1a; 在汽车CAN总线通信中&#xff0c;DBC文件里的信号处理&#xff08;如初始值、系数、偏移&#xff09;主要是为了 将原始二进制数据转换为实际物理值&#xff0c;确保不同电子控制单元&…

【五.LangChain技术与应用】【8.LangChain提示词模板基础:从入门到精通】

早上八点,你端着咖啡打开IDE,老板刚甩来需求:“做个能自动生成产品描述的AI工具”。你自信满满地打开ChatGPT的API文档,结果半小时后对着满屏的"输出结果不稳定"、"格式总出错"抓耳挠腮——这时候你真需要好好认识下LangChain里的提示词模板了。 一、…

LeetCode 718.最长重复子数组(动态规划,Python)

给两个整数数组 nums1 和 nums2 &#xff0c;返回 两个数组中 公共的 、长度最长的子数组的长度 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,3,2,1], nums2 [3,2,1,4,7] 输出&#xff1a;3 解释&#xff1a;长度最长的公共子数组是 [3,2,1] 。 示例 2&#xff1a; 输…

python-leetcode-零钱兑换 II

518. 零钱兑换 II - 力扣&#xff08;LeetCode&#xff09; 这个问题是 完全背包问题 的一个变体&#xff0c;可以使用 动态规划 来解决。我们定义 dp[i] 为凑成金额 i 的硬币组合数。 思路&#xff1a; 定义 DP 数组 设 dp[i] 表示凑成金额 i 的组合数&#xff0c;初始化 dp[…

Sass 模块化革命:深入解析 @use 语法,打造高效 CSS 架构

文章目录 前言use 用法1. 模块化与命名空间2. use 中 as 语法的使用3. as * 语法的使用4. 私有成员的访问5. use 中with默认值6. use 导入问题总结下一篇预告&#xff1a; 前言 在上一篇中&#xff0c;我们深入探讨了 Sass 中 import 语法的局限性&#xff0c;正是因为这些问题…

利用Postman和Apipost进行API测试的实践与优化-动态参数

在实际的开发和测试工作中&#xff0c;完成一个API后对其进行简单的测试是一项至关重要的任务。在测试过程中&#xff0c;确保API返回的数据符合预期&#xff0c;不仅可以提高开发效率&#xff0c;还能帮助我们快速发现可能存在的问题。对于简单的API测试&#xff0c;诸如验证响…

【前端基础】Day 9 PC端品优购项目

目录 1. 品优购项目规划 1.1 网站制作流程 1.2 品优购项目整体介绍 1.3 学习目的 1.4 开发工具以及技术栈 1.5 项目搭建工作 1.6 网站favicon图标 1.7 网站TDK三大标签SEO优化 2. 品优购首页制作 2.1 常见模块类命名 2.2 快捷导航shortcut制作 2.3 header制作 2.4…

FFMPEG利用H264+AAC合成TS文件

本次的DEMO是利用FFMPEG框架把H264文件和AAC文件合并成一个TS文件。这个DEMO很重要&#xff0c;因为在后面的推流项目中用到了这方面的技术。所以&#xff0c;大家最好把这个项目好好了解。 下面这个是流程图 从这个图我们能看出来&#xff0c;在main函数中我们主要做了这几步&…

Linux搭建个人大模型RAG-(ollama+deepseek+anythingLLM)

本文是远程安装ollama deepseek&#xff0c;本地笔记本电脑安装anythingLLM&#xff0c;并上传本地文件作为知识库。 1.安装ollama 安装可以非常简单&#xff0c;一行命令完事。&#xff08;有没有GPU&#xff0c;都没有关系&#xff0c;自动下载合适的版本&#xff09; cd 到…

Docker 学习(二)——基于Registry、Harbor搭建私有仓库

Docker仓库是集中存储和管理Docker镜像的平台&#xff0c;支持镜像的上传、下载、版本管理等功能。 一、Docker仓库分类 1.公有仓库 Docker Hub&#xff1a;官方默认公共仓库&#xff0c;提供超过10万镜像&#xff0c;支持用户上传和管理镜像。 第三方平台&#xff1a;如阿里…

韩国互联网巨头 NAVER 如何借助 StarRocks 实现实时数据洞察

作者&#xff1a; Youngjin Kim Team Leader, NAVER Moweon Lee Data Engineer, NAVER 导读&#xff1a;开源无国界&#xff0c;在“StarRocks 全球用户精选案例”专栏中&#xff0c;我们将介绍韩国互联网巨头 NAVER 的 StarRocks 实践案例。 NAVER 成立于 1999 年&#xff0…

C语言学习笔记-初阶(30)深入理解指针2

1. 数组名的理解 在上一个章节我们在使用指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这里我们使用 &arr[0] 的方式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&…

【Wireshark 02】抓包过滤方法

一、官方教程 Wireshark 官网文档 &#xff1a; Wireshark User’s Guide 二、显示过滤器 2.1、 “数据包列表”窗格的弹出过滤菜单 例如&#xff0c;源ip地址作为过滤选项&#xff0c;右击源ip->prepare as filter-> 选中 点击选中完&#xff0c;显示过滤器&#…

MySQL基础四(JDBC)

JDBC(重点) 数据库驱动 程序会通过数据库驱动&#xff0c;和数据库打交道。 sun公司为了简化开发人员对数据库的统一操作&#xff0c;提供了一个Java操作数据库的规范。这个规范由具体的厂商去完成。对应开发人员来说&#xff0c;只需要掌握JDBC接口。 熟悉java.sql与javax.s…

基于CURL命令封装的JAVA通用HTTP工具

文章目录 一、简要概述二、封装过程1. 引入依赖2. 定义脚本执行类 三、单元测试四、其他资源 一、简要概述 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具&#xff0c;可以说是一款很强大的http命令行工具。它支持文件的上传和下载&#xff0c;是综合传输工具&…

cenos7网络安全检查

很多网络爱好者都知道&#xff0c;在Windows 2000和Windows 9x的命令提示符下可使用Windows系统自带的多种命令行网络故障检测工具&#xff0c;比如说我们最常用的ping。但大家在具体应用时&#xff0c;可能对这些命令行工具的具体含义&#xff0c;以及命令行后面可以使用的种…

蓝桥杯C组真题——巧克力

题目如下 思路 代码及解析如下 谢谢观看

The Rust Programming Language 学习 (三)

所有权 所有权&#xff08;系统&#xff09;是 Rust 最为与众不同的特性&#xff0c;它让 Rust 无需垃圾回收器&#xff08;garbage collector&#xff09;即可保证内存安全。因此&#xff0c;理解 Rust 中所有权的运作方式非常重要。 这里是非常重非常重的一个知识点,这里一…

【一个月备战蓝桥算法】递归与递推

字典序 在刷题和计算机科学领域&#xff0c;字典序&#xff08;Lexicographical order&#xff09;也称为词典序、字典顺序、字母序&#xff0c;是一种对序列元素进行排序的方式&#xff0c;它模仿了字典中单词的排序规则。下面从不同的数据类型来详细解释字典序&#xff1a; …