rk3288硬解库libvpu硬解出来的格式是不是YUV420SP,需要手动转成420P

如题?

是的 ,仅支持此格式。

isle 发表于 2016-4-1 09:40
是的 ,仅支持此格式。

硬解的时候,有一些帧(I帧及后续的P帧)会硬解失败导致视频局部花怎么办?我试了遇到I帧硬解失败就换软解,但不太可行。版主有没有什么好的办法解决硬解失败的情况?

isle 发表于 2016-4-1 09:40
是的 ,仅支持此格式。

[mw_shl_code=c,false]static int hsdec_init(AVCodecContext* avctx)
{
ff_h264_decode_init(avctx);
rkdec_init(avctx);
return 0;
}
static inline int is_key_frame(AVPacket* packet) {
return (packet->flags & AV_PKT_FLAG_KEY);
}
static int hsdec_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *packet)
{
int ret = 0;
static int use_soft = 0;
static int cnt = 0;
int is_key = is_key_frame(packet);
cnt++;

if (is_key) {
    printf("idx:%d is key frame.\n", cnt);
}
use_soft = 1;
if ((use_soft == 0) && is_key) {
    use_soft = 0;
	ret = rkdec_decode_frame(avctx, data, got_frame, packet);
	if ((*got_frame == 0) && is_key) {
        printf("idx:%d hw decode failed, use software decoding.\n", cnt);
        ret = h264_decode_frame(avctx, data, got_frame, packet);
        if (*got_frame == 0 || ret != 0) {
            printf("idx:%d soft decoding also failed, use hw decoding.\n", cnt);
            use_soft = 0;
        } else {
            use_soft = 1;
        }

        use_soft = 1;
    }
} else {
    ret = h264_decode_frame(avctx, data, got_frame, packet);
    if (*got_frame == 0 || ret != 0) {
        printf("soft decoding failed.\n");
    }
}

return ret;

}

static int hsdec_deinit(AVCodecContext *avctx)
{
rkdec_deinit(avctx);
h264_decode_end(avctx);
return 0;
}

#define OFFSET(x) offsetof(H264Context, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption h264_options = {
{“is_avc”, “is avc”, offsetof(H264Context, is_avc), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0},
{“nal_length_size”, “nal_length_size”, offsetof(H264Context, nal_length_size), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 4, 0},
{ “enable_er”, “Enable error resilience on damaged frames (unsafe)”, OFFSET(enable_er), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VD },
{ NULL },
};

static const AVClass h264_class = {
.class_name = “H264 Decoder”,
.item_name = av_default_item_name,
.option = h264_options,
.version = LIBAVUTIL_VERSION_INT,
};

static const AVProfile profiles = {
{ FF_PROFILE_H264_BASELINE, “Baseline” },
{ FF_PROFILE_H264_CONSTRAINED_BASELINE, “Constrained Baseline” },
{ FF_PROFILE_H264_MAIN, “Main” },
{ FF_PROFILE_H264_EXTENDED, “Extended” },
{ FF_PROFILE_H264_HIGH, “High” },
{ FF_PROFILE_H264_HIGH_10, “High 10” },
{ FF_PROFILE_H264_HIGH_10_INTRA, “High 10 Intra” },
{ FF_PROFILE_H264_HIGH_422, “High 4:2:2” },
{ FF_PROFILE_H264_HIGH_422_INTRA, “High 4:2:2 Intra” },
{ FF_PROFILE_H264_HIGH_444, “High 4:4:4” },
{ FF_PROFILE_H264_HIGH_444_PREDICTIVE, “High 4:4:4 Predictive” },
{ FF_PROFILE_H264_HIGH_444_INTRA, “High 4:4:4 Intra” },
{ FF_PROFILE_H264_CAVLC_444, “CAVLC 4:4:4” },
{ FF_PROFILE_UNKNOWN },
};

static int decode_init_thread_copy(AVCodecContext *avctx)
{
H264Context h = &(((H264HSDecContext)avctx->priv_data)->soft_decode_ctx);;
int ret;

if (!avctx->internal->is_copy)
    return 0;

memset(h, 0, sizeof(*h));

ret = h264_init_context(avctx, h);
if (ret < 0)
    return ret;

h->context_initialized = 0;

return 0;

}

AVCodec ff_h264_hs_decoder = {
.name = “h264_hs”,
.long_name = NULL_IF_CONFIG_SMALL(“h264_hs compund decoder”),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.priv_data_size = sizeof(H264HSDecContext),
.init = hsdec_init,
.close = hsdec_deinit,
.decode = hsdec_decode_frame,
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
.flush = rkdec_decode_flush,
.pix_fmts = (const enum AVPixelFormat) {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
},
.init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context),
.profiles = NULL_IF_CONFIG_SMALL(profiles),
.priv_class = &h264_class,
}; [/mw_shl_code]

我重写的一个H264解码器,集成了软硬解, 多加了这几个字段,不加软解失败,加了软解也崩溃 .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context),
.profiles = NULL_IF_CONFIG_SMALL(profiles),
.priv_class = &h264_class,

正常来说,一般的H264格式都能正常解。解花屏基本上都是送数据出错。可以参考我在linux上实现硬解的帖子。

isle 发表于 2016-4-1 16:51
正常来说,一般的H264格式都能正常解。解花屏基本上都是送数据出错。可以参考我在linux上实现硬解的帖子。

一个视频文件只有开始一小部分出错啊,难道一个视频文件还有两种不同的编码方式?

应该是你送数据送的不对!

isle 发表于 2016-4-1 17:56
应该是你送数据送的不对!

对比了下软解,软解是成功的。
使用场景是这样的,ffmpeg集成了硬解,使用ffplay播放h264视频。
软解成功,硬解前面几帧是失败的。
日志图片


我有libvpu的代码,加上了几行printf,可以看出是硬解失败,调用get_frame函数从llist(解码后的帧放到此list中)拿不到数据导致pDecOut->size = 0;