HarmonyOS 鸿蒙Next ArrayBuffer要怎么转化成yuv数据?

发布于 1周前 作者 yibo5220 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next ArrayBuffer要怎么转化成yuv数据?

ArrayBuffer要怎么转化成yuv数据?这块可以用native c++来实现?是否有demo,

2 回复

1、可以使用FFmpeg三方库来进行转换,链接编译出来的ffmpeg库,编译参考:

https://gitee.com/openharmony-sig/tpc_c_cplusplus/tree/master/thirdparty/FFmpeg/docs

调用FFmpeg将png转换为yuv,使用参考:

#include <iostream>
#include <fstream>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <tuple>

extern “C” { #include <stdio.h> #include <stdlib.h> #include <unistd.h>

#include <libavcodec/avcodec.h>

#include <libavformat/avformat.h> #include <libavformat/avio.h>

#include <libavutil/audio_fifo.h> #include <libavutil/avassert.h> #include <libavutil/avstring.h> #include <libavutil/dict.h> #include <libavutil/frame.h> #include <libavutil/imgutils.h> #include <libavutil/opt.h> #include <libavutil/pixdesc.h> #include <libavutil/samplefmt.h> #include <libavutil/time.h> #include <libavutil/timestamp.h>

#include <libavfilter/buffersink.h> #include <libavfilter/buffersrc.h> #include <libavfilter/avfilter.h>

#include <libswresample/swresample.h> }

int main() { std::cout << “Hello World!” << std::endl; printf(“ffmpeg version:%s\n”, av_version_info());

int ret = <span class="hljs-number"><span class="hljs-number">0</span></span>;

<span class="hljs-comment"><span class="hljs-comment">// input yuv</span></span>
<span class="hljs-comment"><span class="hljs-comment">//打开png图片</span></span>
<span class="hljs-comment"><span class="hljs-comment">// png转换为yuv指令为:ffmpeg -i %4d.png -pix_fmt yuv420p -s 1984x1344 out.yuv</span></span>

FILE *inFile = NULL;
<span class="hljs-keyword"><span class="hljs-keyword">const</span></span> char *inFileName = <span class="hljs-string"><span class="hljs-string">"bg.png"</span></span>;
inFile = fopen(inFileName, <span class="hljs-string"><span class="hljs-string">"rb+"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!inFile)
{
	printf(<span class="hljs-string"><span class="hljs-string">"Fail to open file\n"</span></span>);
	<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> -<span class="hljs-number"><span class="hljs-number">1</span></span>;
}

int in_width = <span class="hljs-number"><span class="hljs-number">48</span></span>;
int in_height = <span class="hljs-number"><span class="hljs-number">48</span></span>;

<span class="hljs-comment"><span class="hljs-comment">// output yuv</span></span>
FILE *outFile = NULL;
<span class="hljs-keyword"><span class="hljs-keyword">const</span></span> char *outFileName = <span class="hljs-string"><span class="hljs-string">"output.yuv"</span></span>;
outFile = fopen( outFileName, <span class="hljs-string"><span class="hljs-string">"wb"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!outFile)
{
	printf(<span class="hljs-string"><span class="hljs-string">"Fail to create file for output\n"</span></span>);
	<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> -<span class="hljs-number"><span class="hljs-number">1</span></span>;
}

AVFormatContext  *pFormatCtx = NULL;
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (avformat_open_input(&amp;pFormatCtx, inFileName, NULL, NULL) != <span class="hljs-number"><span class="hljs-number">0</span></span>)
{
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Couldn't open input filen"</span></span>);
	<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> -<span class="hljs-number"><span class="hljs-number">1</span></span>;
}

<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (avformat_find_stream_info(pFormatCtx,<span class="hljs-number"><span class="hljs-number">0</span></span>) &lt; <span class="hljs-number"><span class="hljs-number">0</span></span>){
	fprintf(stderr ,<span class="hljs-string"><span class="hljs-string">"av_find_stream_info ERRORn"</span></span>);
	<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> -<span class="hljs-number"><span class="hljs-number">1</span></span>;
}

int videoStream = -<span class="hljs-number"><span class="hljs-number">1</span></span>;
<span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (int i = <span class="hljs-number"><span class="hljs-number">0</span></span>; i &lt; pFormatCtx-&gt;nb_streams; i++)
{
	<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pFormatCtx-&gt;streams[i]-&gt;codec-&gt;codec_type == AVMEDIA_TYPE_VIDEO)
	{
		videoStream = i;
		fprintf(stderr ,<span class="hljs-string"><span class="hljs-string">"the first video stream index: videoStream = %d\n"</span></span>, videoStream);
		<span class="hljs-keyword"><span class="hljs-keyword">break</span></span>;
	}
}
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (videoStream == -<span class="hljs-number"><span class="hljs-number">1</span></span>)
	<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> -<span class="hljs-number"><span class="hljs-number">1</span></span>; <span class="hljs-comment"><span class="hljs-comment">// Didn't find a video stream</span></span>

AVCodecContext *codeCtx = pFormatCtx-&gt;streams[videoStream]-&gt;codec;
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!codeCtx)
{
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Could not allocate video codec context\n"</span></span>);
	exit(<span class="hljs-number"><span class="hljs-number">1</span></span>);
}

std::cout &lt;&lt; <span class="hljs-string"><span class="hljs-string">"pix_fmt:"</span></span> &lt;&lt; codeCtx-&gt;pix_fmt &lt;&lt; std::endl;

<span class="hljs-comment"><span class="hljs-comment">//打开mp4文件</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">const</span></span> AVCodec *codec = avcodec_find_decoder(codeCtx-&gt;codec_id);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!codec)
{
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Codec not found\n"</span></span>);
	exit(<span class="hljs-number"><span class="hljs-number">1</span></span>);
}

<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (avcodec_open2(codeCtx, codec, NULL) &lt; <span class="hljs-number"><span class="hljs-number">0</span></span>)
{
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Could not open codec\n"</span></span>);
	exit(<span class="hljs-number"><span class="hljs-number">1</span></span>);
}

AVFrame *frame = av_frame_alloc();
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!frame)
{
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Could not allocate video frame\n"</span></span>);
	exit(<span class="hljs-number"><span class="hljs-number">1</span></span>);
}

AVPacket *pkt = av_packet_alloc();
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!pkt){
	fprintf(stderr, <span class="hljs-string"><span class="hljs-string">"Could not allocate video packet\n"</span></span>);
	exit(<span class="hljs-number"><span class="hljs-number">1</span></span>);
}

uint8_t *video_dst_data[<span class="hljs-number"><span class="hljs-number">4</span></span>] = {NULL};
int video_dst_linesize[<span class="hljs-number"><span class="hljs-number">4</span></span>] = {<span class="hljs-number"><span class="hljs-number">0</span></span>};
ret = av_image_alloc(video_dst_data, video_dst_linesize, in_width, in_height, codeCtx-&gt;pix_fmt,<span class="hljs-number"><span class="hljs-number">1</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (ret &lt; <span class="hljs-number"><span class="hljs-number">0</span></span>){

}
int video_dst_bufsize = ret;

int indexNum = <span class="hljs-number"><span class="hljs-number">1</span></span>;
<span class="hljs-keyword"><span class="hljs-keyword">while</span></span> (av_read_frame(pFormatCtx, pkt) &gt;= <span class="hljs-number"><span class="hljs-number">0</span></span>)
{
	<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pkt-&gt;stream_index == videoStream){
		ret = avcodec_send_packet(codeCtx,pkt);

		<span class="hljs-keyword"><span class="hljs-keyword">while</span></span>(ret &gt;= <span class="hljs-number"><span class="hljs-number">0</span></span>){
			ret = avcodec_receive_frame(codeCtx,frame);
			<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (ret &lt; <span class="hljs-number"><span class="hljs-number">0</span></span> || ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
			{
				<span class="hljs-keyword"><span class="hljs-keyword">break</span></span>;
			}

			<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (codeCtx-&gt;codec-&gt;type == AVMEDIA_TYPE_VIDEO){
				<span class="hljs-comment"><span class="hljs-comment">//获取到了yuv视频帧</span></span>
				av_image_copy(video_dst_data, video_dst_linesize,
							  (<span class="hljs-keyword"><span class="hljs-keyword">const</span></span> uint8_t **)(frame-&gt;data), frame-&gt;linesize,
							  codeCtx-&gt;pix_fmt, in_width, in_height);
				char tmpstr[<span class="hljs-number"><span class="hljs-number">100</span></span>] = {};
				sprintf(tmpstr, <span class="hljs-string"><span class="hljs-string">"yuv-%d.yuv"</span></span>, indexNum);
				FILE *f1;
				f1 = fopen(tmpstr, <span class="hljs-string"><span class="hljs-string">"wb"</span></span>);
				fwrite(video_dst_data[<span class="hljs-number"><span class="hljs-number">0</span></span>], <span class="hljs-number"><span class="hljs-number">1</span></span>, video_dst_bufsize, f1);
				fclose(f1);
				indexNum++;
			}
		}
	}
	av_packet_unref(pkt);
	<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (ret &lt; <span class="hljs-number"><span class="hljs-number">0</span></span>)
		<span class="hljs-keyword"><span class="hljs-keyword">break</span></span>;
}

fclose(inFile);
fclose(outFile);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-number"><span class="hljs-number">0</span></span>;

} <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

2、直接转换,参考:https://blog.csdn.net/pzp49666/article/details/105363001

在HarmonyOS(鸿蒙)系统中,将ArrayBuffer转化成YUV数据通常涉及到对图像数据的处理和格式转换。ArrayBuffer本身是一个通用的、固定长度的原始二进制数据缓冲区,而YUV则是一种颜色编码格式,常用于视频和图像处理。

要实现这一转换,你需要执行以下步骤:

  1. 确定ArrayBuffer的内容:首先,需要明确ArrayBuffer中存储的数据格式,比如是否是RGB、RGBA或其他格式。这将决定后续转换的具体步骤。

  2. 提取像素数据:根据ArrayBuffer的内容格式,提取出每个像素的RGB(或RGBA)值。

  3. 转换颜色空间:将提取出的RGB(或RGBA)值转换为YUV格式。这通常涉及复杂的数学运算,包括颜色空间的线性变换和可能的非线性处理(如伽马校正)。

  4. 组织YUV数据:根据YUV的具体格式(如YUV420、YUV422等),将转换后的数据组织成相应的结构。

由于这一转换过程涉及较复杂的图像处理算法,建议使用专门的图像处理库或API来简化这一过程。在HarmonyOS中,你可以探索使用系统提供的多媒体处理API或第三方图像处理库来实现这一功能。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部