文章目录

        • 博客简介 . FFMPEG 编解码器获取流程
        • I . FFMPEG 获取音视频流的编解码参数 AVCodecParameters *codecpar
        • II . FFMPEG 查找解码器 avcodec_find_decoder ( )
        • III . FFMPEG 获取编解码器上下文 avcodec_alloc_context3 ( )
        • IV . FFMPEG 设置编解码器上下文参数 avcodec_parameters_to_context ( )
        • V . FFMPEG 打开编解码器 avcodec_open2 ( )
        • VI . FFMPEG 获取编解码器 代码示例



博客简介 . FFMPEG 编解码器获取流程



FFMPEG 编解码器获取流程 : 在获取音视频流 AVStream *stream 之后 , 执行以下流程 ;


〇 获取 AVStream * 音视频流 ( 获取编解码器前提 ) : 参考博客 【Android FFMPEG 开发】FFMPEG 获取 AVStream 音视频流 ( AVFormatContext 结构体 | 获取音视频流信息 | 获取音视频流个数 | 获取音视频流 )


① 获取音视频流的编码参数 : AVStream *stream 结构体的 AVCodecParameters *codecpar 元素是音视频流的编解码参数 ; 包含 码率 , 宽度 , 高度 , 采样率 等参数信息 ;

//解码这个媒体流的参数信息 , 包含 码率 , 宽度 , 高度 , 采样率 等参数信息AVCodecParameters *codecParameters = stream->codecpar;

② 查找编解码器 : 调用 avcodec_find_decoder ( ) 获取当前音视频流使用的编解码器 ;

//① 查找 当前流 使用的编码方式 , 进而查找编解码器 ( 可能失败 , 不支持的解码方式 )AVCodec *avCodec = avcodec_find_decoder(codecParameters->codec_id);

③ 获取编解码器上下文 : 调用 avcodec_alloc_context3 ( ) 方法 , 获取编解码器上下文 ;

//② 获取编解码器上下文AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);

④ 设置编解码器上下文参数 : 调用 avcodec_parameters_to_context ( ) 方法 , 设置编解码器的上下文参数 ;

//③ 设置 编解码器上下文 参数//      int avcodec_parameters_to_context(AVCodecContext *codec,//              const AVCodecParameters *par);//      返回值 > 0 成功 , < 0 失败int parameters_to_context_result =        avcodec_parameters_to_context(avCodecContext, codecParameters);

⑤ 打开编解码器 : 调用 avcodec_open2 ( ) 方法 , 打开编解码器 ;

//④ 打开编解码器//   int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, //   返回 0 成功 , 其它失败int open_codec_result = avcodec_open2(avCodecContext, avCodec, 0);


I . FFMPEG 获取音视频流的编解码参数 AVCodecParameters *codecpar



1 . 编解码参数封装在 AVStream 结构体中 : FFMPEG 音视频流的编码参数 AVCodecParameters *codecpar 是 AVStream 结构体的元素 ;

/** * Stream structure. * New fields can be added to the end with minor version bumps. * Removal, reordering and changes to existing fields require a major * version bump. * sizeof(AVStream) must not be used outside libav*. */typedef struct AVStream {.../**     * Codec parameters associated with this stream. Allocated and freed by     * libavformat in avformat_new_stream() and avformat_free_context()     * respectively.     *     * - demuxing: filled by libavformat on stream creation or in     *             avformat_find_stream_info()     * - muxing: filled by the caller before avformat_write_header()     */    AVCodecParameters *codecpar;...}AVStream;

2 . FFMPEG 获取音视频流的编码参数 示例 : 其中 AVStream *stream 是之前获取的音视频流结构体指针 ;

//解码这个媒体流的参数信息 , 包含 码率 , 宽度 , 高度 , 采样率 等参数信息AVCodecParameters *codecParameters = stream->codecpar;

3 . 编解码参数 AVCodecParameters *codecpar 中封装的数据 : 这里只列举我们需要使用的 ;

① enum AVCodecID codec_id : 编解码器使用的编码数据的特定类型 , 需要使用该值获取解码器 ;

/** * This struct describes the properties of an encoded stream. * * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must * be allocated with avcodec_parameters_alloc() and freed with * avcodec_parameters_free(). */typedef struct AVCodecParameters{...    /**     * Specific type of the encoded data (the codec used).     */    enum AVCodecID   codec_id;    ...}AVCodecParameters;


II . FFMPEG 查找解码器 avcodec_find_decoder ( )



1 . avcodec_find_decoder ( ) 函数原型 : 根据编解码器 ID , 查找被注册的解码器 ;


① enum AVCodecID id 参数 : 代表了一个编码数据的特定类型 ; ( 详情查看 I . 3 . ① 小节内容 )

② AVCodec *avCodec 返回值 : 返回值是 AVCodec * 结构体指针类型变量 , 代表了获取的解码器 ;

/**avcodec.h * Find a registered decoder with a matching codec ID. * * @param id AVCodecID of the requested decoder * @return A decoder if one was found, NULL otherwise. */AVCodec *avcodec_find_decoder(enum AVCodecID id);

2 . FFMPEG 查找解码器 avcodec_find_decoder ( ) 使用示例 :

//① 查找 当前流 使用的编码方式 , 进而查找编解码器 ( 可能失败 , 不支持的解码方式 )AVCodec *avCodec = avcodec_find_decoder(codecParameters->codec_id);//查找失败处理if(avCodec == NULL){    //如果没有找到编解码器 , 回调失败 , 方法直接返回 , 后续代码不执行    callHelper->onError(pid, 2);    __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "查找 编解码器 失败");    return;}


III . FFMPEG 获取编解码器上下文 avcodec_alloc_context3 ( )



avcodec_alloc_context3 ( ) 函数原型 : 获取编解码器上下文 ;


① const AVCodec *codec 参数 : 要获取上下文的编解码器 ;

② AVCodecContext *avCodecContext 返回值 : 编解码器上下文 , 封装了很多编解码器相关参数 ; 如果为 NULL , 说明获取失败 ;

/**avcodec.h * Allocate an AVCodecContext and set its fields to default values. The * resulting struct should be freed with avcodec_free_context(). * * @param codec if non-NULL, allocate private data and initialize defaults *              for the given codec. It is illegal to then call avcodec_open2() *              with a different codec. *              If NULL, then the codec-specific defaults won't be initialized, *              which may result in suboptimal default settings (this is *              important mainly for encoders, e.g. libx264). * * @return An AVCodecContext filled with default values or NULL on failure. */AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

2 . FFMPEG 获取编解码器上下文 avcodec_alloc_context3 ( ) 使用示例 :

//② 获取编解码器上下文AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);//获取编解码器失败处理if(avCodecContext == NULL){    callHelper->onError(pid, 3);    __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "创建编解码器上下文 失败");    return;}


IV . FFMPEG 设置编解码器上下文参数 avcodec_parameters_to_context ( )



1 . avcodec_parameters_to_context ( ) 函数原型 : 基于编解码器提供的编解码参数设置编解码器上下文参数 ;


① AVCodecContext *codec 参数 : 要设置参数的编解码器上下文 , 这里当做返回值使用 , 这个值之后还要使用 ;

② const AVCodecParameters *par 参数 : 媒体流的参数信息 , 包含 码率 , 宽度 , 高度 , 采样率 等参数信息 , 是 AVStream 结构体封装的元素 ;

③ 返回值 : 如果返回值 >= 0 , 说明设置编解码器上下文参数操作成功 , 如果 < 0 , 设置失败 ;

/** * Fill the codec context based on the values from the supplied codec * parameters. Any allocated fields in codec that have a corresponding field in * par are freed and replaced with duplicates of the corresponding field in par. * Fields in codec that do not have a counterpart in par are not touched. * * @return >= 0 on success, a negative AVERROR code on failure. */int avcodec_parameters_to_context(AVCodecContext *codec,                                  const AVCodecParameters *par);

2 . FFMPEG 设置编解码器上下文参数 avcodec_parameters_to_context ( ) 使用示例 :

//③ 设置 编解码器上下文 参数//      int avcodec_parameters_to_context(AVCodecContext *codec,//              const AVCodecParameters *par);//      返回值 > 0 成功 , < 0 失败int parameters_to_context_result =        avcodec_parameters_to_context(avCodecContext, codecParameters);//设置 编解码器上下文 参数 失败处理if(parameters_to_context_result < 0){    callHelper->onError(pid, 4);    __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "设置编解码器上下文参数 失败");    return;}


V . FFMPEG 打开编解码器 avcodec_open2 ( )



1 . avcodec_open2 ( ) 函数原型 : 打开编解码器 , 之前必须先初始化编解码器上下文 AVCodecContext ;


① AVCodecContext *avctx 参数 : 之前根据编解码器获取上下文参数 avcodec_alloc_context3(avCodec) , 并为其设置了音视频流编解码参数 avcodec_parameters_to_context(avCodecContext, codecParameters) ;

② const AVCodec *codec 参数 : 需要打开的编解码上下文对应的编解码器 ;

③ 返回值 : 返回 0 成功 , 其它值 失败 ;

/** * Initialize the AVCodecContext to use the given AVCodec. Prior to using this * function the context has to be allocated with avcodec_alloc_context3(). * * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for * retrieving a codec. * * @warning This function is not thread safe! * * @note Always call this function before using decoding routines (such as * @ref avcodec_receive_frame()). * * @code * avcodec_register_all(); * av_dict_set(&opts, "b", "2.5M", 0); * codec = avcodec_find_decoder(AV_CODEC_ID_H264); * if (!codec) *     exit(1); * * context = avcodec_alloc_context3(codec); * * if (avcodec_open2(context, codec, opts) < 0) *     exit(1); * @endcode * * @param avctx The context to initialize. * @param codec The codec to open this context for. If a non-NULL codec has been *              previously passed to avcodec_alloc_context3() or *              for this context, then this parameter MUST be either NULL or *              equal to the previously passed codec. * @param options A dictionary filled with AVCodecContext and codec-private options. *                On return this object will be filled with options that were not found. * * @return zero on success, a negative value on error * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), *      av_dict_set(), av_opt_find(). */int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

2 . FFMPEG 打开编解码器 avcodec_open2 ( ) 使用示例 :

//④ 打开编解码器//   int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);//   返回 0 成功 , 其它失败int open_codec_result = avcodec_open2(avCodecContext, avCodec, 0);//打开编解码器 失败处理if(open_codec_result != 0){    callHelper->onError(pid, 5);    __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "打开 编解码器 失败");    return;}


VI . FFMPEG 获取编解码器 代码示例



        //视频 / 音频 处理需要的操作 ( 获取编解码器 )        //① 查找 当前流 使用的编码方式 , 进而查找编解码器 ( 可能失败 , 不支持的解码方式 )        AVCodec *avCodec = avcodec_find_decoder(codecParameters->codec_id);        //查找失败处理        if(avCodec == NULL){            //如果没有找到编解码器 , 回调失败 , 方法直接返回 , 后续代码不执行            callHelper->onError(pid, 2);            __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "查找 编解码器 失败");            return;        }        //② 获取编解码器上下文        AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);        //获取编解码器失败处理        if(avCodecContext == NULL){            callHelper->onError(pid, 3);            __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "创建编解码器上下文 失败");            return;        }        //③ 设置 编解码器上下文 参数        //      int avcodec_parameters_to_context(AVCodecContext *codec,        //              const AVCodecParameters *par);        //      返回值 > 0 成功 , < 0 失败        int parameters_to_context_result =                avcodec_parameters_to_context(avCodecContext, codecParameters);        //设置 编解码器上下文 参数 失败处理        if(parameters_to_context_result < 0){            callHelper->onError(pid, 4);            __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "设置编解码器上下文参数 失败");            return;        }        //④ 打开编解码器        //   int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);        //   返回 0 成功 , 其它失败        int open_codec_result = avcodec_open2(avCodecContext, avCodec, 0);        //打开编解码器 失败处理        if(open_codec_result != 0){            callHelper->onError(pid, 5);            __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "打开 编解码器 失败");            return;        }

更多相关文章

  1. Android canvas.drawXXX参数问题
  2. android添加文件打开方式以及参数传递
  3. android使用Navigation实现Fragment之间的跳转之二:参数传递
  4. android的上下文菜单
  5. android Studio 使用gradle 参数解释及多渠道打包
  6. android 自动化压力测试-monkey 3 命令参数
  7. android上下文之间参数的传递与接…
  8. Android调用系统相机onActivityResult返回参数data为null
  9. android intent activity参数传递

随机推荐

  1. Android 硬件抽象层(HAL)概要介绍和学习计
  2. Android UI框架 Android UI控件类简介 an
  3. Android平台各类恶意软件及病毒概览
  4. Android studio简单使用JNI实例
  5. AndroidX将替代 Android支持库(android.s
  6. Android(安卓)实现定时闹铃功能
  7. Android打包AAR及与unity通信方法
  8. 浅析Android(安卓)M新功能Adoptable Stor
  9. Android开发之实现两个手机之间的通讯
  10. 解决Android AVD启动报错问题