如题?
是的 ,仅支持此格式。
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;

