• 第五章 音视频-FFmpeg实现播放器解封装、读AVPacket包


    第五章 音视频-FFmpeg实现播放器解封装、读AVPacket包

    第一章 音视频-FFmpeg解码流程和对应结构参数意
    第二章 音视频-FFmpeg对应解析格式说明
    第三章 音视频-FFmpeg对应AVFrame解码处理思路和用途
    第四章 音视频-FFmpeg实现播放器思维
    第五章 音视频-FFmpeg实现播放器解封装、读AVPacket包
    第六章 音视频-FFmpeg实现播放器解码和对应数据处理

    ffmpeg解封装

    媒体文件进行解封装,在做播放器步骤前一个章节进行解封装,解封装可以自己进行C++ 或者c语言封装一个通过方法,获取相关结构体,结构体在第一章有做介绍,下面代码本人封装的一个通过方法,读取媒体文件可能只有音频或者视频,也可能同时有音视频,也可以只读取你要音频或者视频。

    typedef struct {
        AVCodecContext *video_dec_ctx;
        AVCodecContext *audio_dec_ctx;
        AVFormatContext *dec_fmt_ctx;
        AVCodecContext *video_enc_ctx;
        AVCodecContext *audio_enc_ctx;
        double video_rotate;
    
        int in_video_stream_index;
        int in_audio_stream_index;
        int out_video_stream_index;     // 0
    } media_info;
    
    
    static double video_get_rotation(AVStream *st)
    {
        uint8_t* displaymatrix = av_stream_get_side_data(st,
                                                         AV_PKT_DATA_DISPLAYMATRIX, NULL);
        double theta = 0;
        if (displaymatrix)
            theta = -av_display_rotation_get((int32_t*) displaymatrix);
    
        theta -= 360*floor(theta/360 + 0.9/360);
    
        if (fabs(theta - 90*round(theta/90)) > 2)
            av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n"
                                         "If you want to help, upload a sample "
                                         "of this file to ftp://upload.ffmpeg.org/incoming/ "
                                         "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)");
    
        return theta;
    }
    
    
    
    /**
     * 打开文件
     * @param filename 文件路径
     * @param info 读取文件数据
     * @param type选择读取是什么AVStream,0是读取所有
     * @return
     */
     int open_input_video(const char *filename,media_info **info,int type){
        AVFormatContext* fmt_ctx =NULL;
    
        AVDictionary *opts = NULL;
        media_info* streamEntity;
        int ret;
    
        streamEntity = (media_info*)av_mallocz_array(1, sizeof(media_info));
        if (!streamEntity){
            MGTED_ERROR("=======av_mallocz_array=error==");
            return AVERROR(ENOMEM);
        }
    
        streamEntity->in_video_stream_index = -1;
        streamEntity->out_video_stream_index = 0;
        streamEntity->video_rotate = 0;
        
        if((ret=avformat_open_input(&fmt_ctx,filename,NULL,NULL))<0){
            MGTED_ERROR("=======avformat_open_input=ret=%d",ret);
            return ret;
        }
        fmt_ctx->probesize = 5000000 << 1;//从源文件中读取的最大字节数,单位为字节
        fmt_ctx->max_analyze_duration  = 90*AV_TIME_BASE;//是从文件中读取的最大时长,单位为 AV_TIME_BASE
        if((ret=avformat_find_stream_info(fmt_ctx,NULL))<0){
            MGTED_ERROR("=======avformat_find_stream_info==ret=%d",ret);
            return ret;
        }
        for (int i = 0; i < fmt_ctx->nb_streams; ++i) {
            AVStream* stream= fmt_ctx->streams[i];
            if (type==1){
                if(stream->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
                    continue;
                }
            } else if (type==2){
                if(stream->codecpar->codec_type==AVMEDIA_TYPE_AUDIO){
                    continue;
                }
            }
            if(stream->codecpar->codec_type==AVMEDIA_TYPE_VIDEO||
               stream->codecpar->codec_type==AVMEDIA_TYPE_AUDIO){
                AVCodec* codec=avcodec_find_decoder(stream->codecpar->codec_id);
                if(!codec){
                    MGTED_ERROR("====avcodec_find_decoder=error=i=%d",i);
                    return AVERROR_DECODER_NOT_FOUND;
                }
                AVCodecContext* avCodecContext=avcodec_alloc_context3(codec);
                if(!avCodecContext){
                    MGTED_ERROR("====avcodec_alloc_context3=error=i=%d",i);
                    return AVERROR(ENOMEM);
                }
               // avCodecContext->thread_count = 4; //设置解码器线程数
                ret=avcodec_parameters_to_context(avCodecContext,stream->codecpar);
                if(ret<0){
                    MGTED_ERROR("====avcodec_parameters_to_context=ret=%d=i=%d",ret,i);
                    return ret;
                }
                if(avCodecContext->codec_type==AVMEDIA_TYPE_VIDEO){
                    /* Open decoder */
                    if (!av_dict_get(opts, "threads", NULL, 0))
                        av_dict_set(&opts, "threads", "auto", 0);
                    av_dict_set(&opts, "refcounted_frames", "0", 0);
                    ret = avcodec_open2(avCodecContext,codec,NULL);
                    if(ret<0){
                        MGTED_ERROR("====avcodec_open2=ret=%d=i=%d",ret,i);
                        return ret;
                    }
                    int angle=video_get_rotation(stream);
                    streamEntity[0].video_dec_ctx = avCodecContext;
                    streamEntity[0].in_video_stream_index = i;
                    streamEntity[0].video_rotate = angle;
                } else{
                    ret = avcodec_open2(avCodecContext,codec,NULL);
                    if(ret<0){
                        MGTED_ERROR("====avcodec_open2=ret=%d=i=%d",ret,i);
                        return ret;
                    }
    
                    streamEntity[0].audio_dec_ctx = avCodecContext;
                    streamEntity[0].in_audio_stream_index = i;
                }
    
            }
        }
        streamEntity[0].dec_fmt_ctx=fmt_ctx;
        *info = streamEntity;
        return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129

    ffmpeg读AVPacket包

    下面对媒体文件进行读包,下面代码封装媒体读包处理,直播流要进行改,正常读包可以参考,为什么要读包,对相应包可以做对应解码,通过上面代码解封装可以获取dec_fmt_ctx格式上下文就可以读报。

            while(1){
               AVPacket packet = { .data = NULL, .size = 0 };
               ret=av_read_frame(info->dec_fmt_ctx,&packet);
               if(ret>=0){
                   if(packet.stream_index==AVMEDIA_TYPE_VIDEO ){//视频包
                       av_packet_unref(&packet);
                   } else if(packet.stream_index==AVMEDIA_TYPE_AUDIO){//音频包
                       av_packet_unref(&packet);
                   } else{
                       av_packet_unref(&packet);
                   }
               } else{
                   av_packet_unref(&packet);
                   if (ret == AVERROR(EAGAIN)) {
                       av_usleep(10000);//延迟10ms
                   }else if (ret ==AVERROR_EOF) {//结束
                       break;
                   }  else{//错误
                       break;
                   }
               }
           }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    下载安装jdk和eclipse详细步骤带图
    【python】待君有余暇,看春赏樱花,这不得来一场浪漫的樱花旅~
    cilantro 点云均值漂移算法(MeanShift)
    C++:模板(初级)
    前端基础建设与架构06 core-js 及垫片理念:设计一个“最完美”的 Polyfill 方案
    提取coco格式json信息生成图片mask
    POI XWPFDocument 实现word中内容换行
    【VMware vSphere】搭建属于自己的 vSphere 实验环境(2)——FreeNA的安装与初始化配置
    RocketMQ相关概念
    数据一致性离不开的checkpoint机制
  • 原文地址:https://blog.csdn.net/u012836015/article/details/139039165