FFmpeg实现解封装

2018-08-14  本文已影响212人  PuHJ

一、关键函数介绍:

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);
上一篇下一篇

猜你喜欢

热点阅读