mediacodec配置h265解码

参考ffmpeg解析vps,sps和pps:

在ffmpeg中可以参考下面的函数是如何解析extradata得到vps,sps,pps的:

hevc_decode_extradata()


AVCodecContext中 extradata 的 parse

aligned(8) class HEVCDecoderConfigurationRecord
{
    unsigned int(8) configurationVersion = 1;
    unsigned int(2) general_profile_space;
    unsigned int(1) general_tier_flag;
    unsigned int(5) general_profile_idc;
    unsigned int(32) general_profile_compatibility_flags;
    unsigned int(48) general_constraint_indicator_flags;
    unsigned int(8) general_level_idc;
    bit(4) reserved = ‘1111’b;
    unsigned int(12) min_spatial_segmentation_idc;
    bit(6) reserved = ‘111111’b;
    unsigned int(2) parallelismType;
    bit(6) reserved = ‘111111’b;
    unsigned int(2) chroma_format_idc;
    bit(5) reserved = ‘11111’b;
    unsigned int(3) bit_depth_luma_minus8;
    bit(5) reserved = ‘11111’b;
    unsigned int(3) bit_depth_chroma_minus8;
    bit(16) avgFrameRate;
    bit(2) constantFrameRate;
    bit(3) numTemporalLayers;
    bit(1) temporalIdNested;
    unsigned int(2) lengthSizeMinusOne;
    unsigned int(8) numOfArrays;
    for (j=0; j < numOfArrays; j++)
    {
        bit(1) array_completeness;
        unsigned int(1) reserved = 0;
        unsigned int(6) NAL_unit_type;
        unsigned int(16) numNalus;
        for (i=0; i< numNalus; i++)
        {
            unsigned int(16) nalUnitLength;
            bit(8*nalUnitLength) nalUnit;
        }
    }
}


从AVCodecContext读取h265的vps,sps,pps信息

        vps_length = (mCodec->extradata[26] * 256) + mCodec->extradata[27];
        sps_length = (mCodec->extradata[28 + vps_length + 3] * 256) + mCodec->extradata[28 + vps_length + 4]; 
        pps_length = (mCodec->extradata[28 + vps_length + 5 + sps_length + 3] * 256) + mCodec->extradata[28 + vps_length + 5 + sps_length + 4]; 

        if ((sps_length > INFO_LENGTH) || (pps_length > INFO_LENGTH)) {
                ulog_err("UHwDecoderVideo::init failed! sps_length=%d, pps_length=%d, longer than length %d", sps_length, pps_length, INFO_LENGTH);
                return -1; 
        }   

        for (i = 0; i < vps_length; i++) {
                sps[i] = mCodec->extradata[i + 28];
        }   
        for (i = 0; i < sps_length; i++) {
                pps[count] = mCodec->extradata[i + 28 + vps_length + 5]; 
                count++;
        }   
        pps[count++] = 0; pps[count++] = 0; pps[count++] = 0; pps[count++] = 1;
        for (i = 0; i < pps_length; i++) {
                pps[count] = mCodec->extradata[i + 28 + vps_length + 5 + sps_length + 5]; 
                count++;
        }   

        // print extra data for debug
        //for (i = 0; i < mCodec->extradata_size; i++) {
                //snprintf(tmp_str, sizeof(tmp_str), "0x%x ", mCodec->extradata[i]);
        for (i = 0; i < vps_length; i++) {
                snprintf(tmp_str, sizeof(tmp_str), "0x%x ", sps[i]);
                strncat(extra_str, tmp_str, strlen(tmp_str));
        }   
        //ulog_info("UHwDecoderVideo::init extradata_size=%d, extradata=%s", mCodec->extradata_size, extra_str);
        ulog_info("UHwDecoderVideo::init sps_size=%d, sps=%s", count, extra_str);
        ulog_info("UHwDecoderVideo::init vps_length=%d sps_length=%d, pps_length=%d, count=%d", vps_length, sps_length, pps_length, count);

        //init decoder
        //ret = Java_com_youku_uplayer_initDecoder(sps, sps_length, pps, pps_length);
        ret = Java_com_youku_uplayer_initDecoder(sps, vps_length, pps, count);
        if (0 == ret) {
                mHwThreadIsRunning = true;
        }   

Mediacodec

解码h265,mediacodec的接口初始化时,需要在csd-0 buffer中填入vps,sps,pps信息;注意三个参数前都必须加上0,0,0,1的前缀码,后面接着是nalu的两个字节头;


MediaCodec 是 Android 提供的一个用于音视频编解码的 API,通过 MediaCodec 可以实现对 H.264 等常见视频格式的硬解码。下面是一个简单的使用 MediaCodec 解码 H.264 的示例: ```java // 创建 MediaCodec 对象 MediaCodec codec = MediaCodec.createDecoderByType("video/avc"); // 配置 MediaCodec,设置输入数据格式和输出数据 Surface MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height); format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible); codec.configure(format, surface, null, 0); // 启动 MediaCodec codec.start(); // 循环读取 H.264 数据并进行解码 while (decoding) { int inputBufferIndex = codec.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex); // 将 H.264 数据写入 inputBuffer 中 codec.queueInputBuffer(inputBufferIndex, 0, data.length, presentationTimeUs, 0); } MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0); if (outputBufferIndex >= 0) { ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferIndex); // 处理解码后的 YUV 数据 codec.releaseOutputBuffer(outputBufferIndex, true); } } ``` 需要注意的是,在使用 MediaCodec 解码 H.264 数据时,需要将 H.264 数据先解析成 NAL 单元,再将 NAL 单元写入到 inputBuffer 中进行解码。另外,解码后的数据是 YUV 格式的数据,需要根据实际需求进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值