diff --git a/VisionSDK/Ascendffmpeg/README.md b/VisionSDK/Ascendffmpeg/README.md index a310c35117e2e0d49c45b019fd9c7ad78b768496..b39e0ae7b9893dee33dabd7fe86c0a49df1a846e 100644 --- a/VisionSDK/Ascendffmpeg/README.md +++ b/VisionSDK/Ascendffmpeg/README.md @@ -102,6 +102,7 @@ export LD_LIBRARY_PATH=/PATH/TO/mindxsdk-referenceapps/VisionSDK/Ascendffmpeg/as * `-frame_rate` - 指定帧率, [1, 240], 默认为25。 * `-max_bit_rate` - 限制码流的最大比特率, [2, 614400], 默认为 20000。 * `-movement_scene` - 指定视频场景(0:静态场景(监控视频等), 1:动态场景(直播,游戏等)), 默认为 1。 +* `-force_I_frame` - 强制指定I帧,默认第一帧为I帧,取值范围为大于0的整数。当取值范围不大于0或者大于视频总帧数时,该参数失效。 **可参考的指令样例(test.264为h264视频):** ```bash @@ -111,7 +112,7 @@ export LD_LIBRARY_PATH=/PATH/TO/mindxsdk-referenceapps/VisionSDK/Ascendffmpeg/as ```bash # 将输入文件 test.264 根据指定参数重新编码为H.264格式,输出文件为 out.264 -./ffmpeg -hwaccel ascend -c:v h264_ascend -device_id 0 -channel_id 0 -resize 1024x1000 -i test.264 -c:v h264_ascend -device_id 0 -channel_id 0 -profile 2 -rc_mode 0 -gop 30 -frame_rate 25 -max_bit_rate 20000 out.264 +./ffmpeg -hwaccel ascend -c:v h264_ascend -device_id 0 -channel_id 0 -resize 1024x1000 -i test.264 -c:v h264_ascend -device_id 0 -channel_id 0 -profile 2 -rc_mode 0 -gop 30 -frame_rate 25 -max_bit_rate 20000 -force_I_frame 2 out.264 ``` ```bash diff --git a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c index 7f091358aca75070a09486bfdc25d77a2b0ef84f..e4bd2ca8a5ca64e2713d9197621a837e9da6e602 100644 --- a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c +++ b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.c @@ -418,6 +418,7 @@ static av_cold int ff_himpi_enc_init(AVCodecContext *avctx) AVHWFramesContext *hwframe_ctx; int ret = -1; int bitstream_buf_size = 0; + ctx->frame_index = 0; char device_id[sizeof(int)]; if (avctx == NULL || ctx == NULL) { @@ -589,10 +590,18 @@ 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); - + int ret; + if (ctx->force_I_frame > 0 && ctx->frame_index == ctx->force_I_frame - 1) { + ret = hi_mpi_venc_request_idr(ctx->channel_id, HI_TRUE); + if (ret) { + av_log(ctx, AV_LOG_ERROR, "Set I-frame failed, ret is %d.\n", ret); + return ret; + } + } + hi_venc_start_param recvParam; recvParam.recv_pic_num = -1; - int ret = hi_mpi_venc_start_chn(ctx->channel_id, &recvParam); + ret = hi_mpi_venc_start_chn(ctx->channel_id, &recvParam); if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Call hi_mpi_venc_start_chn failed, ret is %d.\n", ret); return ret; @@ -755,6 +764,7 @@ static int ff_himpi_enc_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) } get_ret = hi_mpi_get_pkt(avctx, avpkt); + ctx->frame_index++; if (get_ret != 0 && get_ret != AVERROR_EOF) { if (get_ret != AVERROR(EAGAIN)) { return get_ret; @@ -880,14 +890,24 @@ static av_cold int ff_himpi_enc_close(AVCodecContext *avctx) #endif static const AVOption options[] = { - { "device_id", "Use to choose the ascend chip.", OFFSET(device_id), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 8, VE}, - { "channel_id", "Set channelId of encoder.", OFFSET(channel_id), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 127, VE}, - { "profile", "0: baseline, 1:main, 2: high. H265 file only support main level.", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = 1}, 0, 2, VE}, - { "rc_mode", "0: CBR mode, 1: VBR mode.", OFFSET(rc_mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 1, VE}, - { "gop", "Set gop of encoder.", OFFSET(gop), AV_OPT_TYPE_INT, { .i64 = 30}, 1, 65536, VE}, - { "frame_rate", "Set input stream frame_rate.", OFFSET(frame_rate), AV_OPT_TYPE_INT, { .i64 = 25}, 1, 240, VE}, - { "max_bit_rate", "Set max_bite_rate of VBR or average_bit_rate of CBR.", OFFSET(max_bit_rate), AV_OPT_TYPE_INT, { .i64 = 20000}, 2, 614400, VE}, - { "movement_scene", "0: static scene, 1: movement scene.", OFFSET(is_movement_scene), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 1, VE}, + { "device_id", "Use to choose the ascend chip.", + OFFSET(device_id), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 8, VE}, + { "channel_id", "Set channelId of encoder.", + OFFSET(channel_id), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 127, VE}, + { "profile", "0: baseline, 1:main, 2: high. H265 file only support main level.", + OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = 1}, 0, 2, VE}, + { "rc_mode", "0: CBR mode, 1: VBR mode.", + OFFSET(rc_mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 1, VE}, + { "gop", "Set gop of encoder.", + OFFSET(gop), AV_OPT_TYPE_INT, { .i64 = 30}, 1, 65536, VE}, + { "frame_rate", "Set input stream frame_rate.", + OFFSET(frame_rate), AV_OPT_TYPE_INT, { .i64 = 25}, 1, 240, VE}, + { "max_bit_rate", "Set max_bite_rate of VBR or average_bit_rate of CBR.", + OFFSET(max_bit_rate), AV_OPT_TYPE_INT, { .i64 = 20000}, 2, 614400, VE}, + { "movement_scene", "0: static scene, 1: movement scene.", + OFFSET(is_movement_scene), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 1, VE}, + { "force_I_frame", "Set the frame as an I-frame.", + OFFSET(force_I_frame), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT64_MAX, VE}, { NULL } }; diff --git a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.h b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.h index 6ba8357cf4c7cb47ed26173d7f5a06bb08d7f769..4b40d38e647f0c13aa0cb648ff8a73a4045d72f8 100644 --- a/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.h +++ b/VisionSDK/Ascendffmpeg/libavcodec/ascend_enc.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,8 @@ typedef struct ASCENDEncContext { int frame_rate; int max_bit_rate; int is_movement_scene; + int64_t force_I_frame; + int64_t frame_index; int coded_width; int coded_height;