FFmpeg實現(xiàn)簡單解碼

一、解碼函數(shù)流程

1、解碼器的注冊
avcodec_register_all();
2、查找解碼器
    //軟解碼器  28(codec_id = h264的) ID號解封裝的時候,音頻也是對應(yīng)的
    AVCodec *codec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
    //硬解碼
    codec = avcodec_find_decoder_by_name("h264_mediacodec");

硬解碼時需設(shè)置一下方法,會自動調(diào)用

extern "C"
JNIEXPORT
jint JNI_OnLoad(JavaVM *vm, void *res) {
    av_jni_set_java_vm(vm, 0);
    return JNI_VERSION_1_4;
}
3、創(chuàng)建和清理編碼環(huán)境
    //解碼器初始化
    AVCodecContext *vc = avcodec_alloc_context3(codec);

   // 清除解碼環(huán)境
   void avcodec_free_context(AVCodecContext **avctx);
4、填充編解碼器上下文
int avcodec_parameters_to_context(AVCodecContext *codec,
                                  const AVCodecParameters *par);
5、打開解碼器
    //打開解碼器
    re = avcodec_open2(vc, 0, 0);

6、開始解碼
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);//將AVPacket 插入到一個隊列中

int avcodec_receive_frame(AVCodecContex t *avctx, AVFrame *frame); // 取出一個解碼好的AVFrame

二、解碼結(jié)構(gòu)體

5、AVFrame(存放解碼后的數(shù)據(jù))
? AVFrame *frame = av_frame_alloc(); //空間分配,創(chuàng)建對象
? void av_frame_free(AVFrame **frame); //釋放
? int av_frame_ref(AVFrame *dst, const AVFrame *src); //增加引用
? AVFrame *av_frame_clone(const AVFrame *src);
? void av_frame_unref(AVFrame *frame);

    /**
     * pointer to the picture/channel planes.
     * */
? uint8_t *data[AV_NUM_DATA_POINTERS];
    /**
     * For video, size in bytes of each picture line.
     * For audio, size in bytes of each plane.
     *
     * For audio, only linesize[0] may be set. For planar audio, each channel
     * plane must be the same size.
     *
     * For video the linesizes should be multiples of the CPUs alignment
     * preference, this is 16 or 32 for modern desktop CPUs.
     * Some code requires such alignment other code can be slower without
     * correct alignment, for yet other it makes no difference.
     *
     * @note The linesize may be larger than the size of usable data -- there
     * may be extra padding present for performance reasons.
     */
? int linesize[AV_NUM_DATA_POINTERS];
? int width, height; //視頻寬高
? int nb_samples; //單通道樣本數(shù)量
? int64_t pts;int64_t pkt_dts;
? int sample_rate;uint64_t channel_layout;int channels;
? int format; //AVPixelFormat AVSampleFormat

三、視頻像素尺寸轉(zhuǎn)換和音頻重采樣

①視頻像素尺寸轉(zhuǎn)換

可以采用shader處理,效率高,這里使用FFmpeg本身函數(shù)。

sws_getContext 得到像素尺寸轉(zhuǎn)化上下文
轉(zhuǎn)換函數(shù)
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
 const int srcStride[], int srcSliceY, int srcSliceH,
 uint8_t *const dst[], const int dstStride[]);

②音頻重采樣

    //音頻重采樣上下文初始化
    SwrContext *actx = swr_alloc();
    actx = swr_alloc_set_opts(actx,
                              av_get_default_channel_layout(2),
                              AV_SAMPLE_FMT_S16, ac->sample_rate,
                              av_get_default_channel_layout(ac->channels),
                              ac->sample_fmt, ac->sample_rate,
                              0, 0);
    swr_init(actx);
/** Convert audio.
 *
 * in and in_count can be set to 0 to flush the last few samples out at the
 * end.
 *
 * If more input is provided than output space, then the input will be buffered.
 * You can avoid this buffering by using swr_get_out_samples() to retrieve an
 * upper bound on the required number of output samples for the given number of
 * input samples. Conversion will run directly without copying whenever possible.
 *
 * @param s         allocated Swr context, with parameters set
 * @param out       output buffers, only the first one need be set in case of packed audio
 * @param out_count amount of space available for output in samples per channel
 * @param in        input buffers, only the first one need to be set in case of packed audio
 * @param in_count  number of input samples available in one channel
 *
 * @return number of samples output per channel, negative value on error
 */
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
                                const uint8_t **in , int in_count);
釋放上下文函數(shù)
void sws_freeContext(struct SwsContext *swsContext);

后記

-- 完整代碼GitHub:https://github.com/puhaojie/testffmpeg

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容