Firefly开源社区

标题: rk3288硬解库libvpu硬解出来的格式是不是YUV420SP,需要手动转成420P [打印本页]

作者: keygen8    时间: 2016-3-28 13:30
标题: rk3288硬解库libvpu硬解出来的格式是不是YUV420SP,需要手动转成420P
如题?
作者: isle    时间: 2016-4-1 09:40
是的 ,仅支持此格式。
作者: keygen8    时间: 2016-4-1 13:46
isle 发表于 2016-4-1 09:40
是的 ,仅支持此格式。

硬解的时候,有一些帧(I帧及后续的P帧)会硬解失败导致视频局部花怎么办?我试了遇到I帧硬解失败就换软解,但不太可行。版主有没有什么好的办法解决硬解失败的情况?
作者: keygen8    时间: 2016-4-1 13:53
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,
作者: isle    时间: 2016-4-1 16:51
正常来说,一般的H264格式都能正常解。解花屏基本上都是送数据出错。可以参考我在linux上实现硬解的帖子。
作者: keygen8    时间: 2016-4-1 17:29
isle 发表于 2016-4-1 16:51
正常来说,一般的H264格式都能正常解。解花屏基本上都是送数据出错。可以参考我在linux上实现硬解的帖子。

一个视频文件只有开始一小部分出错啊,难道一个视频文件还有两种不同的编码方式?
作者: isle    时间: 2016-4-1 17:56
应该是你送数据送的不对!
作者: keygen8    时间: 2016-4-6 14:55
isle 发表于 2016-4-1 17:56
应该是你送数据送的不对!

对比了下软解,软解是成功的。
使用场景是这样的,ffmpeg集成了硬解,使用ffplay播放h264视频。
软解成功,硬解前面几帧是失败的。
日志图片
我有libvpu的代码,加上了几行printf,可以看出是硬解失败,调用get_frame函数从llist(解码后的帧放到此list中)拿不到数据导致pDecOut->size = 0;





欢迎光临 Firefly开源社区 (https://dev.t-firefly.com/) Powered by Discuz! X3.1