美文网首页音视频开发
iOS ijkPlayer改为p2p帧模式播放问题点

iOS ijkPlayer改为p2p帧模式播放问题点

作者: Johnny_Wu | 来源:发表于2020-06-03 10:50 被阅读0次

    一、硬解不支持Hevc

    开启硬解:
    [options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];
    主要原因:
    硬解annex-b格式的视频帧,需要把annex-b转换为Avcc格式。看ijkplayer源码,只有H264的转换函数:ff_isom_write_avcc
    解决办法:
    对于H265,需要把annex-b转换为Hvcc格式,发现有ff_isom_write_hvcc函数,只是没有公开函数。只需要加入hevc.h头文件就可以使用:
    IJKVideoToolBoxSync.m 大概1047行

    if(codecpar->codec_id==AV_CODEC_ID_HEVC)
       ff_isom_write_hvcc(pb, extradata, extrasize,1);
    else
       ff_isom_write_avcc(pb, extradata, extrasize);
    

    后面的validate_avcC_spc校验函数,可以校验H264的,但无法校验H265,可以注释掉,也可以控制只校验H264。

    二、硬解不支持动态分辨率

    开启硬解支持动态分辨率:
    [options setPlayerOptionIntValue:1 forKey:@"videotoolbox-handle-resolution-change"];

    IJKVideoToolBoxSync.m 大概690行 decode_video这个函数内
    主要原因:av_packet_get_side_data这个无法从AVPacket获取到对应的extradata值,猜测这个函数只支持avcc格式,不支持annex-b。

    解决办法:自己实现获取extradata功能
    我项目的主帧的头部是带上sps,pps等信息的。所以我只需从第一个字节获取到主帧标志的前一个字节,就是对应的extradata。具体实现如下:

    static uint8_t s_alBuf[300];
    //by alex 读取extradata videoType:0:H264   1:H265
    static uint8_t *al_packet_get_side_data(AVPacket *avpkt,int *size,int videoType){
        uint8_t *ptr = avpkt->data;
        uint8_t keyFlag = 0x05;     //h264主帧
        if(videoType==1)
            keyFlag = 0x13;     //h265主帧
        int extraSize = 0;
        for(int i=0;i<avpkt->size;i++){
            uint8_t s = ptr[i];
            if(videoType==1)
                s = (s & 0x7E)>>1;
            else
                s = s & 0x1F;
            if(s!=keyFlag){
                continue;
            }
            if(i<=3){
                continue;
            }
            //00000001
            if(ptr[i-1]==1&&ptr[i-2]==0&&ptr[i-3]==0&&ptr[i-4]==0){
                extraSize = i-4;
                break;
            }
            //000001
            if(ptr[i-1]==1&&ptr[i-2]==0&&ptr[i-3]==0){
                extraSize = i-3;
                break;
            }
        }
        if(extraSize>0){
            *size = extraSize;
            int bufSize = sizeof(s_alBuf);
            bufSize = MIN(bufSize, extraSize);
            memset(s_alBuf, 0, sizeof(s_alBuf));
            memcpy(s_alBuf, ptr, bufSize);
            return s_alBuf;
        }
        return NULL;
    }
    

    IJKVideoToolBoxSync.m 的函数decode_video修改如下:
    大概在decode_video函数下面10行

    if (context->ffp->vtb_handle_resolution_change &&
            (context->codecpar->codec_id == AV_CODEC_ID_H264||context->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
            //by alex
            if(ff_avpacket_is_key(avpkt)){
                size_data = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &size_data_size);
                if(!size_data){
                    if(avctx->codec_id == AV_CODEC_ID_HEVC)
                        size_data = al_packet_get_side_data(avpkt, &size_data_size,1);
                    else
                        size_data = al_packet_get_side_data(avpkt, &size_data_size,0);
                }
            }
    

    相关文章

      网友评论

        本文标题:iOS ijkPlayer改为p2p帧模式播放问题点

        本文链接:https://www.haomeiwen.com/subject/yblvzhtx.html