【Android FFMPEG 开发】FFMPEG 获取编解码器 ( 获取编解码参数 | 查找编解码器 | 获取编解码器上下文 | 设置上下文参数 | 打开编解码器 )
文章目錄
- 博客簡介 . FFMPEG 編解碼器獲取流程
- I . FFMPEG 獲取音視頻流的編解碼參數(shù) AVCodecParameters *codecpar
- II . FFMPEG 查找解碼器 avcodec_find_decoder ( )
- III . FFMPEG 獲取編解碼器上下文 avcodec_alloc_context3 ( )
- IV . FFMPEG 設(shè)置編解碼器上下文參數(shù) avcodec_parameters_to_context ( )
- V . FFMPEG 打開編解碼器 avcodec_open2 ( )
- VI . FFMPEG 獲取編解碼器 代碼示例
博客簡介 . FFMPEG 編解碼器獲取流程
FFMPEG 編解碼器獲取流程 : 在獲取音視頻流 AVStream *stream 之后 , 執(zhí)行以下流程 ;
〇 獲取 AVStream * 音視頻流 ( 獲取編解碼器前提 ) : 參考博客 【Android FFMPEG 開發(fā)】FFMPEG 獲取 AVStream 音視頻流 ( AVFormatContext 結(jié)構(gòu)體 | 獲取音視頻流信息 | 獲取音視頻流個數(shù) | 獲取音視頻流 )
① 獲取音視頻流的編碼參數(shù) : AVStream *stream 結(jié)構(gòu)體的 AVCodecParameters *codecpar 元素是音視頻流的編解碼參數(shù) ; 包含 碼率 , 寬度 , 高度 , 采樣率 等參數(shù)信息 ;
//解碼這個媒體流的參數(shù)信息 , 包含 碼率 , 寬度 , 高度 , 采樣率 等參數(shù)信息 AVCodecParameters *codecParameters = stream->codecpar;② 查找編解碼器 : 調(diào)用 avcodec_find_decoder ( ) 獲取當前音視頻流使用的編解碼器 ;
//① 查找 當前流 使用的編碼方式 , 進而查找編解碼器 ( 可能失敗 , 不支持的解碼方式 ) AVCodec *avCodec = avcodec_find_decoder(codecParameters->codec_id);③ 獲取編解碼器上下文 : 調(diào)用 avcodec_alloc_context3 ( ) 方法 , 獲取編解碼器上下文 ;
//② 獲取編解碼器上下文 AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);④ 設(shè)置編解碼器上下文參數(shù) : 調(diào)用 avcodec_parameters_to_context ( ) 方法 , 設(shè)置編解碼器的上下文參數(shù) ;
//③ 設(shè)置 編解碼器上下文 參數(shù) // int avcodec_parameters_to_context(AVCodecContext *codec, // const AVCodecParameters *par); // 返回值 > 0 成功 , < 0 失敗 int parameters_to_context_result =avcodec_parameters_to_context(avCodecContext, codecParameters);⑤ 打開編解碼器 : 調(diào)用 avcodec_open2 ( ) 方法 , 打開編解碼器 ;
//④ 打開編解碼器 // int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, // 返回 0 成功 , 其它失敗 int open_codec_result = avcodec_open2(avCodecContext, avCodec, 0);I . FFMPEG 獲取音視頻流的編解碼參數(shù) AVCodecParameters *codecpar
1 . 編解碼參數(shù)封裝在 AVStream 結(jié)構(gòu)體中 : FFMPEG 音視頻流的編碼參數(shù) AVCodecParameters *codecpar 是 AVStream 結(jié)構(gòu)體的元素 ;
/*** 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 獲取音視頻流的編碼參數(shù) 示例 : 其中 AVStream *stream 是之前獲取的音視頻流結(jié)構(gòu)體指針 ;
//解碼這個媒體流的參數(shù)信息 , 包含 碼率 , 寬度 , 高度 , 采樣率 等參數(shù)信息 AVCodecParameters *codecParameters = stream->codecpar;3 . 編解碼參數(shù) AVCodecParameters *codecpar 中封裝的數(shù)據(jù) : 這里只列舉我們需要使用的 ;
① enum AVCodecID codec_id : 編解碼器使用的編碼數(shù)據(jù)的特定類型 , 需要使用該值獲取解碼器 ;
/*** 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 ( ) 函數(shù)原型 : 根據(jù)編解碼器 ID , 查找被注冊的解碼器 ;
① enum AVCodecID id 參數(shù) : 代表了一個編碼數(shù)據(jù)的特定類型 ; ( 詳情查看 I . 3 . ① 小節(jié)內(nèi)容 )
② AVCodec *avCodec 返回值 : 返回值是 AVCodec * 結(jié)構(gòu)體指針類型變量 , 代表了獲取的解碼器 ;
/** 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){//如果沒有找到編解碼器 , 回調(diào)失敗 , 方法直接返回 , 后續(xù)代碼不執(zhí)行callHelper->onError(pid, 2);__android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "查找 編解碼器 失敗");return; }III . FFMPEG 獲取編解碼器上下文 avcodec_alloc_context3 ( )
avcodec_alloc_context3 ( ) 函數(shù)原型 : 獲取編解碼器上下文 ;
① const AVCodec *codec 參數(shù) : 要獲取上下文的編解碼器 ;
② AVCodecContext *avCodecContext 返回值 : 編解碼器上下文 , 封裝了很多編解碼器相關(guān)參數(shù) ; 如果為 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" , "創(chuàng)建編解碼器上下文 失敗");return; }IV . FFMPEG 設(shè)置編解碼器上下文參數(shù) avcodec_parameters_to_context ( )
1 . avcodec_parameters_to_context ( ) 函數(shù)原型 : 基于編解碼器提供的編解碼參數(shù)設(shè)置編解碼器上下文參數(shù) ;
① AVCodecContext *codec 參數(shù) : 要設(shè)置參數(shù)的編解碼器上下文 , 這里當做返回值使用 , 這個值之后還要使用 ;
② const AVCodecParameters *par 參數(shù) : 媒體流的參數(shù)信息 , 包含 碼率 , 寬度 , 高度 , 采樣率 等參數(shù)信息 , 是 AVStream 結(jié)構(gòu)體封裝的元素 ;
③ 返回值 : 如果返回值 >= 0 , 說明設(shè)置編解碼器上下文參數(shù)操作成功 , 如果 < 0 , 設(shè)置失敗 ;
/*** 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 設(shè)置編解碼器上下文參數(shù) avcodec_parameters_to_context ( ) 使用示例 :
//③ 設(shè)置 編解碼器上下文 參數(shù) // int avcodec_parameters_to_context(AVCodecContext *codec, // const AVCodecParameters *par); // 返回值 > 0 成功 , < 0 失敗 int parameters_to_context_result =avcodec_parameters_to_context(avCodecContext, codecParameters); //設(shè)置 編解碼器上下文 參數(shù) 失敗處理 if(parameters_to_context_result < 0){callHelper->onError(pid, 4);__android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "設(shè)置編解碼器上下文參數(shù) 失敗");return; }V . FFMPEG 打開編解碼器 avcodec_open2 ( )
1 . avcodec_open2 ( ) 函數(shù)原型 : 打開編解碼器 , 之前必須先初始化編解碼器上下文 AVCodecContext ;
① AVCodecContext *avctx 參數(shù) : 之前根據(jù)編解碼器獲取上下文參數(shù) avcodec_alloc_context3(avCodec) , 并為其設(shè)置了音視頻流編解碼參數(shù) avcodec_parameters_to_context(avCodecContext, codecParameters) ;
② const AVCodec *codec 參數(shù) : 需要打開的編解碼上下文對應(yīng)的編解碼器 ;
③ 返回值 : 返回 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){//如果沒有找到編解碼器 , 回調(diào)失敗 , 方法直接返回 , 后續(xù)代碼不執(zhí)行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" , "創(chuàng)建編解碼器上下文 失敗");return;}//③ 設(shè)置 編解碼器上下文 參數(shù)// int avcodec_parameters_to_context(AVCodecContext *codec,// const AVCodecParameters *par);// 返回值 > 0 成功 , < 0 失敗int parameters_to_context_result =avcodec_parameters_to_context(avCodecContext, codecParameters);//設(shè)置 編解碼器上下文 參數(shù) 失敗處理if(parameters_to_context_result < 0){callHelper->onError(pid, 4);__android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "設(shè)置編解碼器上下文參數(shù) 失敗");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;} 《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的【Android FFMPEG 开发】FFMPEG 获取编解码器 ( 获取编解码参数 | 查找编解码器 | 获取编解码器上下文 | 设置上下文参数 | 打开编解码器 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android FFMPEG 开发】F
- 下一篇: 【Android FFMPEG 开发】F