HarmonyOS 鸿蒙Next ArrayBuffer要怎么转化成yuv数据?
HarmonyOS 鸿蒙Next ArrayBuffer要怎么转化成yuv数据?
ArrayBuffer要怎么转化成yuv数据?这块可以用native c++来实现?是否有demo,
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(&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>) < <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 < pFormatCtx->nb_streams; i++)
{
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pFormatCtx->streams[i]->codec->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->streams[videoStream]->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 << <span class="hljs-string"><span class="hljs-string">"pix_fmt:"</span></span> << codeCtx->pix_fmt << 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->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) < <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->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 < <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) >= <span class="hljs-number"><span class="hljs-number">0</span></span>)
{
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pkt->stream_index == videoStream){
ret = avcodec_send_packet(codeCtx,pkt);
<span class="hljs-keyword"><span class="hljs-keyword">while</span></span>(ret >= <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 < <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->codec->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->data), frame->linesize,
codeCtx->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 < <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则是一种颜色编码格式,常用于视频和图像处理。
要实现这一转换,你需要执行以下步骤:
-
确定ArrayBuffer的内容:首先,需要明确ArrayBuffer中存储的数据格式,比如是否是RGB、RGBA或其他格式。这将决定后续转换的具体步骤。
-
提取像素数据:根据ArrayBuffer的内容格式,提取出每个像素的RGB(或RGBA)值。
-
转换颜色空间:将提取出的RGB(或RGBA)值转换为YUV格式。这通常涉及复杂的数学运算,包括颜色空间的线性变换和可能的非线性处理(如伽马校正)。
-
组织YUV数据:根据YUV的具体格式(如YUV420、YUV422等),将转换后的数据组织成相应的结构。
由于这一转换过程涉及较复杂的图像处理算法,建议使用专门的图像处理库或API来简化这一过程。在HarmonyOS中,你可以探索使用系统提供的多媒体处理API或第三方图像处理库来实现这一功能。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html