美文网首页
FFmpeg实现简单解码

FFmpeg实现简单解码

作者: PuHJ | 来源:发表于2018-08-14 15:55 被阅读52次

    一、解码函数流程

    1、解码器的注册
    avcodec_register_all();
    
    2、查找解码器
        //软解码器  28(codec_id = h264的) ID号解封装的时候,音频也是对应的
        AVCodec *codec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
        //硬解码
        codec = avcodec_find_decoder_by_name("h264_mediacodec");
    

    硬解码时需设置一下方法,会自动调用

    extern "C"
    JNIEXPORT
    jint JNI_OnLoad(JavaVM *vm, void *res) {
        av_jni_set_java_vm(vm, 0);
        return JNI_VERSION_1_4;
    }
    
    3、创建和清理编码环境
        //解码器初始化
        AVCodecContext *vc = avcodec_alloc_context3(codec);
    
       // 清除解码环境
       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
    

    二、解码结构体

    5、AVFrame(存放解码后的数据)
    • AVFrame *frame = av_frame_alloc(); //空间分配,创建对象
    • 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; //单通道样本数量
    • int64_t pts;int64_t pkt_dts;
    • int sample_rate;uint64_t channel_layout;int channels;
    • int format; //AVPixelFormat AVSampleFormat
    

    三、视频像素尺寸转换和音频重采样

    ①视频像素尺寸转换

    可以采用shader处理,效率高,这里使用FFmpeg本身函数。

    sws_getContext 得到像素尺寸转化上下文
    转换函数
    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);
    
    释放上下文函数
    void sws_freeContext(struct SwsContext *swsContext);
    

    后记

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

    相关文章

      网友评论

          本文标题:FFmpeg实现简单解码

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