2023-11-27 14:03:29 +08:00
|
|
|
|
#ifndef HXVIDEODECODER_H
|
|
|
|
|
#define HXVIDEODECODER_H
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
|
|
#include "HxUtils.h"
|
|
|
|
|
|
|
|
|
|
#include <opencv2/opencv.hpp>
|
|
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
|
{
|
|
|
|
|
#include "libavcodec/avcodec.h"
|
|
|
|
|
#include "libavformat/avformat.h"
|
|
|
|
|
#include "libavutil/pixfmt.h"
|
|
|
|
|
#include "libavutil/imgutils.h"
|
|
|
|
|
#include "libswscale/swscale.h"
|
|
|
|
|
#include "libswresample/swresample.h"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if USE_ALGORITHM
|
|
|
|
|
#include "rk_mpi.h"
|
|
|
|
|
#include "mpp_mem.h"
|
|
|
|
|
#include "mpp_time.h"
|
|
|
|
|
#include "mpp_env.h"
|
|
|
|
|
#include "mpp_common.h"
|
|
|
|
|
#include "mpp_frame.h"
|
|
|
|
|
#include "mpp_buffer_impl.h"
|
|
|
|
|
#include "RgaUtils.h"
|
|
|
|
|
#include "im2d.hpp"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
class HxVideoDecoder
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
HxVideoDecoder(void) {}
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
static int duration(QString fullpath)
|
|
|
|
|
{
|
|
|
|
|
/* 始化网络设备 */
|
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
|
|
/* 初始化 */
|
|
|
|
|
AVFormatContext *ifmt_ctx = avformat_alloc_context();
|
|
|
|
|
|
|
|
|
|
/* 打开输入文件 */
|
|
|
|
|
if (avformat_open_input(&ifmt_ctx, fullpath.toUtf8().data(), nullptr, nullptr) < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* 获取流信息 */
|
|
|
|
|
if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0)
|
|
|
|
|
{
|
|
|
|
|
avformat_close_input(&ifmt_ctx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 这里获取的是微秒,需要转成秒 */
|
|
|
|
|
int64_t tduration = ifmt_ctx->duration;
|
|
|
|
|
|
|
|
|
|
/* 打开文件流后,需要关闭,否则会一直占用视频文件,无法进行视频文件的后续操作 */
|
|
|
|
|
avformat_close_input(&ifmt_ctx);
|
|
|
|
|
|
|
|
|
|
/* 销毁 */
|
|
|
|
|
avformat_free_context(ifmt_ctx);
|
|
|
|
|
|
|
|
|
|
return tduration / 1000000;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 14:03:29 +08:00
|
|
|
|
#ifndef USE_ALGORITHM
|
2023-12-08 14:17:14 +08:00
|
|
|
|
void initialization(AVFormatContext *ifmt_ctx)
|
2023-11-27 14:03:29 +08:00
|
|
|
|
{
|
2023-12-08 14:17:14 +08:00
|
|
|
|
status = false;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
auto video_stream_index = -1;
|
|
|
|
|
for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
|
|
|
|
|
{
|
|
|
|
|
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
|
|
video_stream_index = static_cast<int>(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (video_stream_index == -1)
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
|
|
|
|
|
/* 配置解码器 */
|
|
|
|
|
video_dec_ctx = avcodec_alloc_context3(nullptr);
|
|
|
|
|
if (video_dec_ctx == nullptr)
|
|
|
|
|
{
|
|
|
|
|
printf("Could not allocate AVCodecContext");
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 拷贝 */
|
|
|
|
|
avcodec_parameters_to_context(video_dec_ctx, ifmt_ctx->streams[video_stream_index]->codecpar);
|
|
|
|
|
|
|
|
|
|
/* 查找解码器 */
|
|
|
|
|
auto codec = avcodec_find_decoder(video_dec_ctx->codec_id);
|
|
|
|
|
if (!codec)
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
|
|
|
|
|
/* 打开解码器 */
|
|
|
|
|
if (avcodec_open2(video_dec_ctx, codec, nullptr) < 0)
|
|
|
|
|
{
|
|
|
|
|
codec = nullptr;
|
|
|
|
|
avcodec_free_context(&video_dec_ctx);
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
video_dec_frame = av_frame_alloc();
|
|
|
|
|
|
|
|
|
|
video_picture_frame = av_frame_alloc();
|
|
|
|
|
|
|
|
|
|
/* 通过指定像素格式、图像宽、图像高来计算所需的内存大小 */
|
|
|
|
|
auto numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1);
|
|
|
|
|
/* 创建 video_out_buffer */
|
2023-12-08 14:17:14 +08:00
|
|
|
|
video_out_buffer = static_cast<uint8_t *>(av_malloc(static_cast<ulong>(numBytes) * sizeof(uint8_t)));
|
2023-11-27 14:03:29 +08:00
|
|
|
|
/* 填充数据 */
|
|
|
|
|
av_image_fill_arrays(video_picture_frame->data, video_picture_frame->linesize, video_out_buffer, AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1);
|
|
|
|
|
|
|
|
|
|
auto pix_fmt = video_dec_ctx->pix_fmt;
|
|
|
|
|
if (video_dec_ctx->pix_fmt == AVPixelFormat::AV_PIX_FMT_NONE)
|
|
|
|
|
pix_fmt = AV_PIX_FMT_YUV420P;
|
|
|
|
|
|
|
|
|
|
/* 将解码后的YUV数据转换成RGB32 */
|
|
|
|
|
video_sws_context = sws_getContext(
|
|
|
|
|
video_dec_ctx->width, /* 输入图像的宽度 */
|
|
|
|
|
video_dec_ctx->height, /* 输入图像的高度 */
|
|
|
|
|
pix_fmt, /* 输入图像的像素格式 */
|
|
|
|
|
video_dec_ctx->width, /* 输出图像的宽度 */
|
|
|
|
|
video_dec_ctx->height, /* 输出图像的高度 */
|
|
|
|
|
AV_PIX_FMT_BGR24, /* 输出图像的像素格式 */
|
|
|
|
|
SWS_BICUBIC, /* 选择缩放算法(只有当输入输出图像大小不同时有效),一般选择SWS_FAST_BILINEAR */
|
|
|
|
|
nullptr, /* 输入图像的滤波器信息, 若不需要传NULL */
|
|
|
|
|
nullptr, /* 输出图像的滤波器信息, 若不需要传NULL */
|
|
|
|
|
nullptr /* 特定缩放算法需要的参数(?),默认为NULL */
|
|
|
|
|
);
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
status = true;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
#else
|
2023-12-08 14:17:14 +08:00
|
|
|
|
void initialization(void)
|
2023-11-27 14:03:29 +08:00
|
|
|
|
{
|
2023-12-08 14:17:14 +08:00
|
|
|
|
status = false;
|
|
|
|
|
|
2023-11-27 14:03:29 +08:00
|
|
|
|
MPP_RET ret = MPP_OK;
|
|
|
|
|
|
|
|
|
|
RK_U32 need_split = 1;
|
|
|
|
|
|
|
|
|
|
/* 创建 MPP context 和 MPP api 接口 */
|
|
|
|
|
ret = mpp_create(&mpp_ctx, &mpp_mpi);
|
|
|
|
|
if (ret != MPP_OK)
|
|
|
|
|
{
|
|
|
|
|
release();
|
|
|
|
|
|
|
|
|
|
HxLog::append("mpp", QString("mpp_create failed"));
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 配置解器 按帧输入码流 */
|
2023-12-08 14:17:14 +08:00
|
|
|
|
ret = mpp_mpi->control(mpp_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, (MppParam *)&need_split);
|
2023-11-27 14:03:29 +08:00
|
|
|
|
if (MPP_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
release();
|
|
|
|
|
|
|
|
|
|
HxLog::append("mpp", QString("mpi->control failed"));
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 配置解器 队列输入 */
|
2023-12-08 14:17:14 +08:00
|
|
|
|
ret = mpp_mpi->control(mpp_ctx, MPP_SET_INPUT_BLOCK, (MppParam *)&need_split);
|
2023-11-27 14:03:29 +08:00
|
|
|
|
if (MPP_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
release();
|
|
|
|
|
|
|
|
|
|
HxLog::append("mpp", QString("mpi->control failed"));
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 初始化 MPP (固定为H264) */
|
|
|
|
|
ret = mpp_init(mpp_ctx, MPP_CTX_DEC, MPP_VIDEO_CodingAVC);
|
|
|
|
|
if (MPP_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
release();
|
|
|
|
|
|
|
|
|
|
HxLog::append("mpp", QString("mpp_init failed"));
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
status = true;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void release(void)
|
|
|
|
|
{
|
|
|
|
|
#ifndef USE_ALGORITHM
|
|
|
|
|
if (video_dec_ctx)
|
|
|
|
|
{
|
|
|
|
|
avcodec_free_context(&video_dec_ctx);
|
|
|
|
|
avcodec_close(video_dec_ctx);
|
|
|
|
|
|
|
|
|
|
av_frame_free(&video_dec_frame);
|
|
|
|
|
av_frame_free(&video_picture_frame);
|
|
|
|
|
sws_freeContext(video_sws_context);
|
|
|
|
|
|
|
|
|
|
if (video_out_buffer)
|
|
|
|
|
av_free(video_out_buffer);
|
|
|
|
|
video_out_buffer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (mpp_ctx)
|
|
|
|
|
{
|
|
|
|
|
mpp_mpi->reset(mpp_ctx);
|
|
|
|
|
mpp_destroy(mpp_ctx);
|
|
|
|
|
mpp_ctx = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mpp_frame_group)
|
|
|
|
|
{
|
|
|
|
|
mpp_buffer_group_put(mpp_frame_group);
|
|
|
|
|
mpp_frame_group = nullptr;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
void decode(AVPacket *packet, cv::Mat *mat)
|
2023-11-27 14:03:29 +08:00
|
|
|
|
{
|
|
|
|
|
#ifndef USE_ALGORITHM
|
|
|
|
|
/* 发送数据到ffmepg,放到解码队列中 */
|
|
|
|
|
if (avcodec_send_packet(video_dec_ctx, packet) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* 将成功的解码队列中取出1个frame */
|
|
|
|
|
if (avcodec_receive_frame(video_dec_ctx, video_dec_frame) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* 开始转换 */
|
2023-12-08 14:17:14 +08:00
|
|
|
|
sws_scale(video_sws_context, static_cast<const uint8_t *const *>(video_dec_frame->data), video_dec_frame->linesize, 0, video_dec_ctx->height, video_picture_frame->data, video_picture_frame->linesize);
|
2023-11-27 14:03:29 +08:00
|
|
|
|
|
|
|
|
|
(*mat) = cv::Mat(cv::Size(video_dec_ctx->width, video_dec_ctx->height), CV_8UC3);
|
|
|
|
|
(*mat).data = video_out_buffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
RK_U32 pkt_done = 0;
|
|
|
|
|
RK_U32 pkt_eos = 0;
|
|
|
|
|
RK_U32 err_info = 0;
|
|
|
|
|
MPP_RET ret = MPP_OK;
|
|
|
|
|
MppPacket mpp_packet = nullptr;
|
|
|
|
|
MppFrame mpp_frame = nullptr;
|
|
|
|
|
|
|
|
|
|
ret = mpp_packet_init(&mpp_packet, packet->data, packet->size);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mpp_packet_set_pts(mpp_packet, packet->pts);
|
|
|
|
|
|
|
|
|
|
// qDebug("av_packet->data:%hhn", packet->data);
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
// msleep(1);
|
|
|
|
|
|
|
|
|
|
RK_S32 count = 5;
|
|
|
|
|
// send the packet first if packet is not done
|
|
|
|
|
if (!pkt_done)
|
|
|
|
|
{
|
|
|
|
|
ret = mpp_mpi->decode_put_packet(mpp_ctx, mpp_packet);
|
|
|
|
|
if (MPP_OK == ret)
|
|
|
|
|
pkt_done = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// then get all available frame and release
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
// msleep(1);
|
|
|
|
|
|
|
|
|
|
RK_S32 get_frm = 0;
|
|
|
|
|
RK_U32 frame_eos = 0;
|
|
|
|
|
|
|
|
|
|
try_again:
|
|
|
|
|
ret = mpp_mpi->decode_get_frame(mpp_ctx, &mpp_frame);
|
|
|
|
|
if (MPP_ERR_TIMEOUT == ret)
|
|
|
|
|
{
|
|
|
|
|
if (count > 0)
|
|
|
|
|
{
|
|
|
|
|
count--;
|
|
|
|
|
msleep(2);
|
|
|
|
|
goto try_again;
|
|
|
|
|
}
|
|
|
|
|
qDebug("decode_get_frame failed too much time");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// qDebug("get MPP_OK:%d", MPP_OK);
|
|
|
|
|
// qDebug("get ret:%d", ret);
|
|
|
|
|
if (MPP_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
qDebug("decode_get_frame failed ret %d", ret);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// qDebug("get frame:%p", mpp_frame);
|
|
|
|
|
|
|
|
|
|
if (mpp_frame)
|
|
|
|
|
{
|
|
|
|
|
if (mpp_frame_get_info_change(mpp_frame))
|
|
|
|
|
{
|
|
|
|
|
RK_U32 width = mpp_frame_get_width(mpp_frame);
|
|
|
|
|
RK_U32 height = mpp_frame_get_height(mpp_frame);
|
|
|
|
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(mpp_frame);
|
|
|
|
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(mpp_frame);
|
|
|
|
|
RK_U32 buf_size = mpp_frame_get_buf_size(mpp_frame);
|
|
|
|
|
|
|
|
|
|
qDebug("decode_get_frame get info changed found");
|
|
|
|
|
qDebug("decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d", width, height, hor_stride, ver_stride, buf_size);
|
|
|
|
|
|
|
|
|
|
ret = mpp_buffer_group_get_internal(&mpp_frame_group, MPP_BUFFER_TYPE_ION);
|
|
|
|
|
if (ret)
|
|
|
|
|
{
|
|
|
|
|
qDebug("get mpp buffer group failed ret %d", ret);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mpp_mpi->control(mpp_ctx, MPP_DEC_SET_EXT_BUF_GROUP, mpp_frame_group);
|
|
|
|
|
|
|
|
|
|
mpp_mpi->control(mpp_ctx, MPP_DEC_SET_INFO_CHANGE_READY, nullptr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
err_info = mpp_frame_get_errinfo(mpp_frame) | mpp_frame_get_discard(mpp_frame);
|
|
|
|
|
if (err_info)
|
|
|
|
|
{
|
|
|
|
|
qDebug("decoder_get_frame get err info:%d discard:%d.",
|
2023-12-08 14:17:14 +08:00
|
|
|
|
mpp_frame_get_errinfo(mpp_frame), mpp_frame_get_discard(mpp_frame));
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
frame_count++;
|
|
|
|
|
// qDebug("decode_get_frame get frame %d", frame_count);
|
|
|
|
|
|
|
|
|
|
if (!err_info)
|
|
|
|
|
{
|
|
|
|
|
RK_U32 width = mpp_frame_get_width(mpp_frame);
|
|
|
|
|
RK_U32 height = mpp_frame_get_height(mpp_frame);
|
|
|
|
|
MppBuffer mpp_buffer = mpp_frame_get_buffer(mpp_frame);
|
|
|
|
|
convert_to_mat(mpp_buffer, width, height, mat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
frame_eos = mpp_frame_get_eos(mpp_frame);
|
|
|
|
|
mpp_frame_deinit(&mpp_frame);
|
|
|
|
|
|
|
|
|
|
mpp_frame = nullptr;
|
|
|
|
|
get_frm = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 尝试获取运行时帧内存使用情况 */
|
|
|
|
|
if (mpp_frame_group)
|
|
|
|
|
{
|
|
|
|
|
size_t usage = mpp_buffer_group_usage(mpp_frame_group);
|
|
|
|
|
if (usage > max_usage)
|
|
|
|
|
max_usage = usage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 如果发送了最后一个数据包,但没有找到最后一帧,则继续 */
|
|
|
|
|
if (pkt_eos && pkt_done && !frame_eos)
|
|
|
|
|
{
|
|
|
|
|
msleep(10);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frame_eos)
|
|
|
|
|
{
|
|
|
|
|
qDebug("found last frame");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frame_num > 0 && frame_count >= frame_num)
|
|
|
|
|
{
|
|
|
|
|
eos = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (get_frm)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
|
|
if (frame_num > 0 && frame_count >= frame_num)
|
|
|
|
|
{
|
|
|
|
|
eos = 1;
|
|
|
|
|
qDebug("reach max frame number %d", frame_count);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pkt_done)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* why sleep here:
|
|
|
|
|
* mpi->decode_put_packet will failed when packet in internal queue is
|
|
|
|
|
* full,waiting the package is consumed .Usually hardware decode one
|
|
|
|
|
* frame which resolution is 1080p needs 2 ms,so here we sleep 3ms
|
|
|
|
|
* * is enough.
|
|
|
|
|
*/
|
|
|
|
|
msleep(3);
|
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
|
|
mpp_packet_deinit(&mpp_packet);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if USE_ALGORITHM
|
|
|
|
|
size_t mpp_buffer_group_usage(MppBufferGroup group)
|
|
|
|
|
{
|
|
|
|
|
if (group == nullptr)
|
|
|
|
|
{
|
|
|
|
|
qDebug("input invalid group %p", group);
|
|
|
|
|
return MPP_BUFFER_MODE_BUTT;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
return ((MppBufferGroupImpl *)group)->usage;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
bool convert_to_mat(MppBuffer mpp_buffer, RK_U32 width, RK_U32 height, cv::Mat *mat)
|
2023-11-27 14:03:29 +08:00
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
im_rect src_rect, dst_rect;
|
|
|
|
|
rga_buffer_t src_img, dst_img;
|
|
|
|
|
|
|
|
|
|
mat->create(cv::Size(width, height), CV_8UC3);
|
|
|
|
|
|
|
|
|
|
memset(&src_rect, 0, sizeof(src_rect));
|
|
|
|
|
memset(&dst_rect, 0, sizeof(dst_rect));
|
|
|
|
|
memset(&src_img, 0, sizeof(src_img));
|
|
|
|
|
memset(&dst_img, 0, sizeof(dst_img));
|
|
|
|
|
|
|
|
|
|
src_img = wrapbuffer_virtualaddr(mpp_buffer_get_ptr(mpp_buffer), width, height, RK_FORMAT_YCbCr_420_SP);
|
2023-12-08 14:17:14 +08:00
|
|
|
|
dst_img = wrapbuffer_virtualaddr(mat->data, width, height, RK_FORMAT_YCbCr_422_SP);
|
2023-11-27 14:03:29 +08:00
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
if (src_img.width == 0 || dst_img.width == 0)
|
|
|
|
|
{
|
2023-11-27 14:03:29 +08:00
|
|
|
|
printf("%s, %s\n", __FUNCTION__, imStrError());
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
src_img.format = RK_FORMAT_YCbCr_420_SP;
|
2023-12-08 14:17:14 +08:00
|
|
|
|
dst_img.format = RK_FORMAT_YCbCr_422_SP;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
ret = imcheck(src_img, dst_img, src_rect, dst_rect);
|
2023-12-08 14:17:14 +08:00
|
|
|
|
if (IM_STATUS_NOERROR != ret)
|
|
|
|
|
{
|
2023-11-27 14:03:29 +08:00
|
|
|
|
printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto STATUS = imcvtcolor(src_img, dst_img, src_img.format, dst_img.format);
|
|
|
|
|
|
|
|
|
|
return STATUS != IM_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
2023-12-08 14:17:14 +08:00
|
|
|
|
public:
|
|
|
|
|
bool status = false;
|
|
|
|
|
|
2023-11-27 14:03:29 +08:00
|
|
|
|
private:
|
|
|
|
|
#if USE_ALGORITHM
|
|
|
|
|
MppCtx mpp_ctx;
|
2023-12-08 14:17:14 +08:00
|
|
|
|
MppApi *mpp_mpi;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
size_t max_usage;
|
|
|
|
|
RK_U32 frame_count = 0, frame_num, eos;
|
|
|
|
|
|
|
|
|
|
/* 缓冲区管理器 */
|
|
|
|
|
MppBufferGroup mpp_frame_group;
|
|
|
|
|
#else
|
2023-12-08 14:17:14 +08:00
|
|
|
|
uint8_t *video_out_buffer = nullptr;
|
|
|
|
|
struct SwsContext *video_sws_context = nullptr;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
|
2023-12-08 14:17:14 +08:00
|
|
|
|
AVCodecContext *video_dec_ctx = nullptr;
|
|
|
|
|
AVFrame *video_dec_frame = nullptr, *video_picture_frame = nullptr;
|
2023-11-27 14:03:29 +08:00
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // HXVIDEODECODER_H
|