美文网首页
ijkplayer上iOS根据AVPacket动态刷新Video

ijkplayer上iOS根据AVPacket动态刷新Video

作者: 睡后3k | 来源:发表于2016-11-10 23:07 被阅读371次

    背景

    项目中有一个切换分辨率的需求,但是服务器更新sps,pps后,并没有在SDP报文中更新sprop-paraemter-sets字段导致VideoToolBox无法解码视频文件

    解决思路

    在av_read_frame后判断nalu_type,如果是7并包含8的话(我们sps,pps是同一个包),刷新VideoToolBox,实现动态码率的效果

    解决方法

    1. 在ff_ffplay.c文件中
      read_thread方法中,找到av_read_frame
      av_read_frame
     //中间是av_read_frame返回结果的判断,在if代码块后添加代码
      .....
      // 00 00 01 的情况在我们的业务中不考虑
       if((pkt->data[4] & 0xF) == 7) {
                        int extradata_size = 0;
                        uint8_t* extradata = NULL;
                        int findpps = 0;
                        for(int index = 4; index < pkt->size ; index++) {
                            //代码比较扭曲,具体就是找到pps后面那个nalu的分隔符
                            if(pkt->data[index] == 0 && pkt->data[index + 1] == 0 && pkt->data[index + 2] == 0){
                                if(!findpps) {
                                    findpps = 1;
                                    continue;
                                }
                                if(findpps) {
                                    extradata_size = index;
                                    extradata = malloc(extradata_size * sizeof(uint8_t));
                                    memcpy(extradata, pkt->data, extradata_size * sizeof(uint8_t));
                                    if(is->video_st->codecpar->extradata) {
                                        free(is->video_st->codecpar->extradata);
                                    }
                                    //拷贝到codecpar中这个两个参数需要在解码器中使用
                                    is->video_st->codecpar->extradata = extradata;
                                    is->video_st->codecpar->extradata_size = extradata_size;
                                    //flush_pkt会激活VideoToolBoxContext的refresh_request
                                    packet_queue_put(&is->videoq, &flush_pkt);
                                    break;
                                }
                            }
                        }
                    }
    
    1. 在IJKVideoToolBox.m中
      在上面已经拿到sps, pps但是在VideoToolBoxContext的codecpar中extradata和extradata_size仍然是旧的,需要主动更新
    static int decode_video_internal(...) {
      ....
      //想看refresh_request什么情况为ture? 直接全局搜 refresh_request = true
      //中间的代码确实没有啥好贴上来的
      if(context->refresh_request) { 
          .....
           if(context->codecpar->extradata) {
                av_free(context->codecpar->extradata);
            }
            context->codecpar->extradata_size = ffp->is->video_st->codecpar->extradata_size;
             //context->extradata和ffp中的extradata都会在shutdown时会释放,所以传指针context->extradata就是成为野指针然后crash
            context->codecpar->extradata = av_memdup(ffp->is->video_st->codecpar->extradata, context->codecpar->extradata_size);
            context->vt_session = vtbsession_create(context);
          .....
      }
      ....
    }
    
    

    相关文章

      网友评论

          本文标题:ijkplayer上iOS根据AVPacket动态刷新Video

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