diff --git a/VisionSDK/Ascendffmpeg/README_DEV.md b/VisionSDK/Ascendffmpeg/README_DEV.md
new file mode 100644
index 0000000000000000000000000000000000000000..bda0525eff6eccd4623c981d2fa220230999b9b1
--- /dev/null
+++ b/VisionSDK/Ascendffmpeg/README_DEV.md
@@ -0,0 +1,140 @@
+## 1 介绍
+
+### 1.1 简介
+
+Vison ascend 硬件平台内置了视频相关的硬件加速编解码器,为了提升用户的易用性,Vision SDK提供了 Ffmepg-Ascend 解决方案。
+
+支持的功能:
+
+|功能|mpeg4|h264/h265| mjpeg |多路 |
+|:----:|:----:|:----:|:-----:|:-------:|
+|硬件解码|√|√| √ | √ |
+|硬件编码|√|√| | √ |
+|硬件转码|√|√| √ | √ |
+|硬件缩放|√|√| | √ |
+
+注意:mjpeg视频流的转码相关功能只在Atlas A500 A2上适用。
+
+### 1.2 支持的产品
+
+本项目支持昇腾Atlas 300I pro、 Atlas 300V pro、 Atlas A500 A2。
+
+### 1.3 支持的版本
+本样例配套的CANN版本、Driver/Firmware版本如下所示:
+
+| CANN版本 | Driver/Firmware版本 |
+| ------------------ | -------------- |
+| 8.0.RC3 | 24.1.RC3 |
+
+
+## 2 设置环境变量
+* `ASCEND_HOME` Ascend 安装的路径,一般为 `/usr/local/Ascend`
+* 执行命令
+ ```bash
+ export ASCEND_HOME=/usr/local/Ascend
+ . /usr/local/Ascend/ascend-toolkit/set_env.sh #toolkit默认安装路径,根据实际安装路径修改
+ ```
+
+
+## 3 编译
+
+**步骤1:** 在项目目录`Ascendffmpeg/`下添加可执行权限:
+```bash
+chmod +x ./configure
+chmod +x ./ffbuild/*.sh
+```
+
+**步骤2:** 在项目目录`Ascendffmpeg/`下执行编译:
+
+编译选项说明:
+* `prefix` - FFmpeg 及相关组件安装目录
+* `enable-shared` - FFmpeg 允许生成 so 文件
+* `extra-cflags` - 添加第三方头文件
+* `extra-ldflags` - 指定第三方库位置
+* `extra-libs` - 添加第三方 so 文件
+* `enable-ascend` - 允许使用 ascend 进行硬件加速
+
+执行编译命令:
+ ```bash
+ ./configure \
+ --prefix=./ascend \
+ --enable-shared \
+ --extra-cflags="-I${ASCEND_HOME}/ascend-toolkit/latest/acllib/include" \
+ --extra-ldflags="-L${ASCEND_HOME}/ascend-toolkit/latest/acllib/lib64" \
+ --extra-libs="-lacl_dvpp_mpi -lascendcl" \
+ --enable-ascend \
+ && make -j && make install
+ ```
+
+**步骤3:** 添加环境变量
+
+通过指令`find / -name libavdevice.so`查找到文件所在路径,形如`/PATH/TO/mindsdk-referenceapps/VisionSDK/Ascendffmpeg/ascend/lib/libavdevice.so`,则执行:
+```bash
+export LD_LIBRARY_PATH=/PATH/TO/mindsdk-referenceapps/VisionSDK/Ascendffmpeg/ascend/lib:$LD_LIBRARY_PATH
+```
+
+
+
+## 4 特性介绍
+
+Ascendffmpeg在ffmpeg开源软件基础上,结合昇腾NPU设备硬件加速,扩充了视频编解码能力。
+
+### 4.1 解码
+
+
+
+ 解码器 |
+ 介绍 |
+
+
+
+ h264_ascend |
+ link |
+
+
+
+ h265_ascend |
+ link |
+
+
+
+ mjpeg_ascend |
+ link |
+
+
+
+
+
+
+### 4.2 编码
+
+
+
+ 编码器 |
+ 介绍 |
+
+
+
+
+ h264_ascend |
+ link |
+
+
+
+
+ h265_ascend |
+ link |
+
+
+
+
+
+## 5 常见问题
+### 5.1 文件编译不通过
+
+问题描述: 文件编译不通过
+
+解决方案: 可能是文件格式被改变或者破坏,建议通过以下两种方式直接获取代码,而非文件传输:
+- 在环境上通过git clone直接下载该代码仓。
+- 直接从代码仓网页gitee下载zip包,并在环境上通过`unzip`解压。
+
diff --git a/VisionSDK/Ascendffmpeg/doc/dec_h26x_ascend.md b/VisionSDK/Ascendffmpeg/doc/dec_h26x_ascend.md
new file mode 100644
index 0000000000000000000000000000000000000000..b175698189de9635a1475c54b00c28a9a2c68e45
--- /dev/null
+++ b/VisionSDK/Ascendffmpeg/doc/dec_h26x_ascend.md
@@ -0,0 +1,81 @@
+## h26x_ascend解码器
+
+### 1 简介
+
+Ffmepg-Ascend 中内置了h264_ascend和h265_ascend解码器,利用昇腾NPU设备分别处理h264视频流和h265视频流的解码。
+
+### 2 头文件
+
+```commandline
+#include "libavcodec/ascend_dec.h"
+```
+
+### 3 特性支持
+
+
+
+
+ 特性 |
+ 参数名 |
+ 类型 |
+ 说明 |
+ h264_ascend |
+ h265_ascend |
+
+
+
+ 指定运行设备 |
+ device_id |
+ int |
+ 取值范围取决于芯片个数,默认为 0。 `npu-smi info` 命令可以查看芯片个数 |
+ ✅ |
+ ✅ |
+
+
+
+ 指定运行通道号 |
+ channel_id |
+ int |
+ 取值范围取决于芯片实际情况,超出时会报错(对于昇腾Atlas 300I pro、 Atlas 300V pro,该参数的取值范围:[0, 256),JPEGD功能和VDEC功能共用通道,且通道总数最多256。对于Atlas 500 A2推理产品,该参数的取值范围:[0, 128),JPEGD功能和VDEC功能共用通道,且通道总数最多128)。 若是指定的通道已被占用, 则自动寻找并申请新的通道。 |
+ ✅ |
+ ✅ |
+
+
+
+ 缩放 |
+ resize_str |
+ char* |
+ 输入格式为: {width}x{height}, 宽高:[128x128-4096x4096] |
+ ✅ |
+ ✅ |
+
+
+
+
+
+### 4 解码器使用
+
+开发态使用解码器代码样例请参考:hw_decode.c |
+
+**特别的**:
+
+解码器默认在“0”号设备上用编号“0”通道进行解码操作,且默认不指定缩放尺寸。
+
+如用户对执行设备,执行通道以及是否缩放有自定义诉求,可以利用“ascend_dec.h”文件中的ASCENDContext_t结构体实现,如下代码所示:
+
+```commandline
+
+ASCENDContext_t* privData = (ASCENDContext_t*)av_malloc(sizeof(ASCENDContext_t));
+privData->device_id = 1; // 用户可自定义修改
+privData->channel_id = 1; // 用户可自定义修改
+privData->resize_str = "1920x1080"; // 用户可自定义修改
+
+AVCodec *decoder; // 假设已经完成对decoder的初始化
+
+AVCodecContext* decoder_ctx = avcodec_alloc_context3(decoder);
+
+decoder_ctx->priv_data = privData; // 将自定义数据传入解码器上下文
+
+/* 执行解码以及相关资源释放 */
+···
+```
diff --git a/VisionSDK/Ascendffmpeg/doc/dec_mjpeg_ascend.md b/VisionSDK/Ascendffmpeg/doc/dec_mjpeg_ascend.md
new file mode 100644
index 0000000000000000000000000000000000000000..77ff989d0eeb27c5b4a7cc012712d269ac2ff60e
--- /dev/null
+++ b/VisionSDK/Ascendffmpeg/doc/dec_mjpeg_ascend.md
@@ -0,0 +1,64 @@
+## mjpeg_ascend解码器
+
+### 1 简介
+
+Ffmepg-Ascend 中内置了mjpeg_ascend解码器,利用昇腾NPU设备处理mjpeg视频流的解码。当前该解码器仅支持在Atlas A500 A2上使用。
+
+### 2 头文件
+
+```commandline
+#include "libavcodec/ascend_mjpeg_dec.h"
+```
+
+### 3 特性支持
+
+
+
+
+ 特性 |
+ 参数名 |
+ 类型 |
+ 说明 |
+ mjpeg_ascend |
+
+
+
+ 指定运行设备 |
+ device_id |
+ int |
+ 取值范围取决于芯片个数,默认为 0。 `npu-smi info` 命令可以查看芯片个数 |
+ ✅ |
+
+
+
+ 指定运行通道号 |
+ channel_id |
+ int |
+ 取值范围取决于芯片实际情况,超出时会报错(对于昇腾Atlas 300I pro、 Atlas 300V pro,该参数的取值范围:[0, 256),JPEGD功能和VDEC功能共用通道,且通道总数最多256。对于Atlas 500 A2推理产品,该参数的取值范围:[0, 128),JPEGD功能和VDEC功能共用通道,且通道总数最多128)。 若是指定的通道已被占用, 则自动寻找并申请新的通道。 |
+ ✅ |
+
+
+
+
+### 4 解码器使用
+
+开发态使用解码器代码样例请参考:hw_decode.c |
+
+
+如用户对执行设备,执行通道有自定义诉求,可以利用“ascend_mjpeg_dec.h”文件中的AscendMJpegDecodeContext结构体实现,如下代码所示:
+
+```commandline
+
+AscendMJpegDecodeContext* privData = (AscendMJpegDecodeContext*)av_malloc(sizeof(AscendMJpegDecodeContext));
+privData->device_id = 1; // 用户可自定义修改
+privData->channel_id = 1; // 用户可自定义修改
+
+AVCodec *decoder; // 假设已经完成对decoder的初始化
+
+AVCodecContext* decoder_ctx = avcodec_alloc_context3(decoder);
+
+decoder_ctx->priv_data = privData; // 将自定义数据传入解码器上下文
+
+/* 执行解码以及相关资源释放 */
+···
+```
diff --git a/VisionSDK/Ascendffmpeg/doc/enc_h26x_ascend.md b/VisionSDK/Ascendffmpeg/doc/enc_h26x_ascend.md
new file mode 100644
index 0000000000000000000000000000000000000000..eca99206034d5e492448fa093717cea7a0ef4c0b
--- /dev/null
+++ b/VisionSDK/Ascendffmpeg/doc/enc_h26x_ascend.md
@@ -0,0 +1,177 @@
+## h26x_ascend编码器
+
+### 1 简介
+
+Ffmepg-Ascend 中内置了h264_ascend和h265_ascend编码器,利用昇腾NPU设备分别处理h264视频流和h265视频流的编码。
+
+### 2 头文件
+
+```commandline
+#include "libavcodec/ascend_enc.h"
+```
+
+### 3 特性支持
+
+
+
+
+ 特性 |
+ 参数名 |
+ 类型 |
+ 说明 |
+ h264_ascend |
+ h265_ascend |
+
+
+
+ 指定运行设备 |
+ device_id |
+ int |
+ 取值范围取决于芯片个数,默认为 0。 `npu-smi info` 命令可以查看芯片个数 |
+ ✅ |
+ ✅ |
+
+
+
+ 指定运行通道号 |
+ channel_id |
+ int |
+ 取值范围取决于芯片实际情况,超出时会报错(对于昇腾Atlas 300I pro、 Atlas 300V pro,该参数的取值范围:[0, 256),JPEGD功能和VDEC功能共用通道,且通道总数最多256。对于Atlas 500 A2推理产品,该参数的取值范围:[0, 128),JPEGD功能和VDEC功能共用通道,且通道总数最多128)。 若是指定的通道已被占用, 则自动寻找并申请新的通道。 |
+ ✅ |
+ ✅ |
+
+
+
+ 指定视频编码的画质级别 |
+ profile |
+ int |
+ 0: baseline, 1: main, 2: high, 默认为 1。 H265 编码器只支持 main |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 指定视频编码器的速率控制模式 |
+ rc_mode |
+ int |
+ 0: CBR, 1: VBR, 默认为 0 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 指定关键帧间隔 |
+ gop |
+ int |
+ [1, 65536], 默认为 30 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 指定帧率 |
+ frame_rate |
+ int |
+ [1, 240], 默认为25 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 限制码流的最大比特率 |
+ max_bit_rate |
+ int |
+ [2, 614400], 默认为 20000 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 指定视频场景 |
+ movement_scene |
+ int |
+ 0:静态场景(监控视频等), 1:动态场景(直播,游戏等), 默认为 1 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+ 强制编码下一帧为I帧 |
+ \ |
+ \ |
+ 该特性需要修改AVFrame中的opaque参数,详情见4.2 |
+ ✅ |
+ ✅ |
+
+
+
+
+
+### 4 编码器使用
+
+开发态使用编码器代码样例请参考:encode_video.c |
+
+
+
+#### 4.1 常规特性使用
+
+如用户对执行设备,执行通道以及其他常规特性有自定义诉求,可以利用“ascend_enc.h”文件中的ASCENDEncContext_t结构体实现,如下代码所示:
+
+```commandline
+
+ASCENDEncContext_t* privData = (ASCENDEncContext_t*)av_malloc(sizeof(ASCENDEncContext_t));
+privData->device_id = 1; // 用户可自定义修改
+privData->channel_id = 1; // 用户可自定义修改
+privData->profile = 0; // 用户可自定义修改
+privData->rc_mode = 0; // 用户可自定义修改
+privData->gop = 25; // 用户可自定义修改
+privData->frame_rate = 25; // 用户可自定义修改
+privData->movement_scene = 0; // 用户可自定义修改
+
+AVCodec *encoder; // 假设已经完成对encoder的初始化
+
+AVCodecContext* encoder_ctx = avcodec_alloc_context3(encoder);
+
+decoder_ctx->priv_data = privData; // 将自定义数据传入编码器上下文
+
+/* 执行编码以及相关资源释放 */
+···
+```
+
+#### 4.2 强制编码下一帧为I帧
+
+该特性通过AVFrame结构体中的opaque指针传递给编码器,如下代码所示:
+
+```commandline
+// 通过AscendEncPrivateData_t来承载是否编码下一帧为I的语义。AscendEncPrivateData_t结构体定义在“liavcodec/avcodec.h”文件中。
+AscendEncPrivateData_t privData = (AscendEncPrivateData_t*)av_malloc(sizeof(AscendEncPrivateData_t));
+privData->next_is_I_frame = true; // 该参数为true时,代表下一帧将会强制编码为I帧
+privData->is_instant = true; // 该参数为true时,立即编出I帧,不受帧率控制约束;该参数为false时,则在帧率控制的下一帧编出I帧。
+ // 当前底层支持场景为目标帧率与原帧率一致,故该参数目前无论设置为true或者false,都是每调用一次接口即可编出一个I帧,调用频繁会影响码流帧率和码率的稳定。
+
+AVCodecContext* enc_ctx; // 假设已完成编码器上下文的初始化
+AVFrame *frame; // 假设已完成AVFrame的初始化
+
+frame->opaque = privData; // 将是否将下一帧编码为I帧的信息赋值给frame
+
+avcodec_send_frame(enc_ctx, frame); // 调用编码器进行编码
+
+/* 获取编码结果 */
+···
+frame->opaque = NULL; // 当编码I帧结束,需要对该参数进行复位,否则后续视频帧都会编码为I帧
+
+/* 释放资源 */
+···
+```
diff --git a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c
index 7f091358aca75070a09486bfdc25d77a2b0ef84f..9bb32bce3d8308fa1b918369c998e4fdee13a358 100644
--- a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c
+++ b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c
@@ -589,7 +589,7 @@ static int hi_mpi_encode(ASCENDEncContext_t *ctx, const AVFrame *frame)
{
av_log(ctx, AV_LOG_DEBUG, "Send frame size: %ux%u, pts:%ld, frame type:%d.\n",
frame->width, frame->height, frame->pts, frame->pict_type);
-
+
hi_venc_start_param recvParam;
recvParam.recv_pic_num = -1;
int ret = hi_mpi_venc_start_chn(ctx->channel_id, &recvParam);
@@ -746,6 +746,15 @@ static int ff_himpi_enc_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
continue;
}
+ AscendEncPrivateData_t* priv_data = frame.opaque;
+ if (priv_data && priv_data->next_is_I_frame) {
+ ret = hi_mpi_venc_request_idr(ctx->channel_id, priv_data->is_instant);
+ if (ret) {
+ av_log(ctx, AV_LOG_ERROR, "Set I-frame failed. ret is %d.\n", ret);
+ return ret;
+ }
+ }
+
send_ret = hi_mpi_encode(ctx, &frame);
av_frame_unref(&frame);
if (send_ret < 0 && send_ret != AVERROR_EOF) {
diff --git a/VisionSDK/Ascendffmpeg/libavcodec/avcodec.h b/VisionSDK/Ascendffmpeg/libavcodec/avcodec.h
index 8a71c042308e37a89dbf357d8f9b276dd4ebcbf9..0cd9750a7404426f78b7678ba5df1086a91a68dd 100644
--- a/VisionSDK/Ascendffmpeg/libavcodec/avcodec.h
+++ b/VisionSDK/Ascendffmpeg/libavcodec/avcodec.h
@@ -28,6 +28,7 @@
*/
#include
+#include
#include "libavutil/samplefmt.h"
#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
@@ -4181,4 +4182,9 @@ AVCPBProperties *av_cpb_properties_alloc(size_t *size);
* @}
*/
+typedef struct AscendEncPrivateData {
+ bool next_is_I_frame;
+ bool is_instant;
+} AscendEncPrivateData_t;
+
#endif /* AVCODEC_AVCODEC_H */