美文网首页
FFmpeg实现解封装

FFmpeg实现解封装

作者: PuHJ | 来源:发表于2018-08-14 14:36 被阅读212次

    一、关键函数介绍:

    1、av_register_all()

    注册所有的解封装格式,也可以根据不同的封装格式,单个注册。

    2、avcodec_register_all()

    网络注册,如rtsp和http的

    3、打开文件
    //AVFormatContext 封装的结构体,创建一个内容为空的指针,内部可以自己管理ic
    AVFormatContext *ic = NULL;  
    int re = avformat_open_input(&ic, path, 0, 0);
    

    根据re的结果可以判断是否成功

    4、获取流信息
     avformat_find_stream_info(ic, 0)
    
    5、获取音频流信息
    //返回的是音频索引
    av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)
    
    6、拖动timestamp时间的frame
    /**
     * Seek to the keyframe at timestamp.
     * 'timestamp' in 'stream_index'.
     *
     * @param s media file handle
     * @param stream_index If stream_index is (-1), a default
     * stream is selected, and timestamp is automatically converted
     * from AV_TIME_BASE units to the stream specific time_base.
     * @param timestamp Timestamp in AVStream.time_base units
     *        or, if no stream is specified, in AV_TIME_BASE units.
     * @param flags flags which select direction and seeking mode
     * @return >= 0 on success
     */
        av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
    
    7、读取下一帧
    // 返回值<0代表错误或者读完了
    int av_read_frame(AVFormatContext *s, AVPacket *pkt);
    

    二、关键结构体介绍:

    1、AVFormatContext
    AVIOContext *pb; // I/O context.自定义格式读或者从内存读可用
    char filename[1024]; // input or output filename
    
     /**
      * Number of elements in AVFormatContext.streams.
     */
    unsigned int nb_streams; // 流的数量
    /**
     * A list of all streams in the file. New streams are created with
     * avformat_new_stream().
     *
     * - demuxing: streams are created by libavformat in avformat_open_input().
     *             If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
     *             appear in av_read_frame().
     * - muxing: streams are created by the user before avformat_write_header().
     *
     * Freed by libavformat in avformat_free_context().
     */
    AVStream **streams; //音视频字幕流
    
    /**
     * Duration of the stream, in AV_TIME_BASE fractional
     * seconds. Only set this value if you know none of the individual stream
     * durations and also do not set any of them. This is deduced from the
     * AVStream values if not set.
     *
     * Demuxing only, set by libavformat.
     */
    int64_t duration; // 获取的总长度(不一定能获取的到,也可通过AVStream获取)
       /**
     * Total stream bitrate in bit/s, 0 if not
     * available. Never set it directly if the file_size and the
     * duration are known as FFmpeg can compute it automatically.
     */
    int64_t bit_rate; // 比特率,网络适应的时候会用
    /**
    * Close an opened input AVFormatContext. Free it and all its contents
    * and set *s to NULL.
    */
    void avformat_close_input(AVFormatContext **s);// 关闭
    
    2、AVStream
        /**
         * This is the fundamental unit of time (in seconds) in terms
         * of which frame timestamps are represented.
         */
        AVRational time_base; //时间基数,通过分子分母计算  (double) r.num / (double) r.den
        /**
         * Decoding: duration of the stream, in stream time base.
         * If a source file does not specify a duration, but does specify
         * a bitrate, this value will be estimated from bitrate and file size.
         *
         * Encoding: May be set by the caller before avformat_write_header() to
         * provide a hint to the muxer about the estimated duration.
         */
        int64_t duration; //换算成秒
    
        int64_t nb_frames;                 ///< number of frames in this stream if known or 0
    
    3、AVCodecParameters

    Codec parameters associated with this stream.

        /**
         * General type of the encoded data.
         */
        enum AVMediaType codec_type; // 标志是否是音频还是视频
        /**
         * Specific type of the encoded data (the codec used).
         */
        enum AVCodecID   codec_id; // 对应的编码格式 h264还是其它的
    
        /**
         * - video: the pixel format, the value corresponds to enum AVPixelFormat.
         * - audio: the sample format, the value corresponds to enum AVSampleFormat.
         */
        int format; // 音视频不一样
        /**
         * Video only. The dimensions of the video frame in pixels.
         */
        int width;
        int height;
        /**
         * Audio only. The number of audio channels.
         */
        int      channels;
        /**
         * Audio only. The number of audio samples per second.
         */
        int      sample_rate;
    
    4、AVPacket
        /**
         * Presentation timestamp in AVStream->time_base units; the time at which
         * the decompressed packet will be presented to the user.
         * Can be AV_NOPTS_VALUE if it is not stored in the file.
         * pts MUST be larger or equal to dts as presentation cannot happen before
         * decompression, unless one wants to view hex dumps. Some formats misuse
         * the terms dts and pts/cts to mean something different. Such timestamps
         * must be converted to true pts/dts before they are stored in AVPacket.
         */
        int64_t pts; // 显示时间
        /**
         * Decompression timestamp in AVStream->time_base units; the time at which
         * the packet is decompressed.
         * Can be AV_NOPTS_VALUE if it is not stored in the file.
         */
        int64_t dts; // 解码时间
        uint8_t *data;
        int   size;
    

    几个重要函数:

      AVPacket *pkt = av_packet_alloc(); //创建对象并初始化
      AVPacket *av_packet_clone(const AVPacket *src);创建并并用计数
      int av_packet_ref(AVPacket *dst, const AVPacket *src);
      av_packet_unref(AVPacket *pkt)
      void av_packet_free(AVPacket **pkt); 清空对象并减引用计数
      void av_init_packet(AVPacket *pkt); 默认值
      int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size);
      int av_copy_packet(AVPacket *dst, const AVPacket *src); attribute_deprecated
    

    3、解封装部分代码

       //初始化解封装
        av_register_all();
        //初始化网络
        avformat_network_init();
    
        avcodec_register_all();
    
        //打开文件
        AVFormatContext *ic = NULL;
        //char path[] = "/sdcard/video.flv";
        int re = avformat_open_input(&ic, path, 0, 0);
        if (re != 0) {
            LOGW("avformat_open_input failed!:%s", av_err2str(re));
            return;
        }
        LOGW("avformat_open_input %s success!", path);
        //获取流信息
        re = avformat_find_stream_info(ic, 0);
        if (re != 0) {
            LOGW("avformat_find_stream_info failed!");
        }
        LOGE("duration = %lld nb_streams = %d", ic->duration, ic->nb_streams);
    
        int fps = 0;
        int videoStream = 0;
        int audioStream = 1;
    
    
    
        /**
         *  音视频属性打印
         */
        for (int i = 0; i < ic->nb_streams; i++) {
            AVStream *as = ic->streams[i];
            // 视频流
            if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                LOGW("视频数据");
                videoStream = i;
                fps = r2d(as->avg_frame_rate);
    
                LOGW("fps = %d,width=%d height=%d codeid=%d pixformat=%d", fps,
                     as->codecpar->width,
                     as->codecpar->height,
                     as->codecpar->codec_id,
                     as->codecpar->format
                );
                //音频流
            } else if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                LOGW("音频数据");
                audioStream = i;
                LOGW("sample_rate=%d channels=%d sample_format=%d",
                     as->codecpar->sample_rate,
                     as->codecpar->channels,
                     as->codecpar->format
                );
            }
        }
    
        // 除了上述中的遍历方法,还可以通过下列av_find_best_stream函数寻找音视频索引
        //获取音频流信息
        audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
        videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);;
        LOGW("av_find_best_stream audioStream = %d  videoStream = %d", audioStream,videoStream);
    

    相关文章

      网友评论

          本文标题:FFmpeg实现解封装

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