FFmpeg实现解封装

一、关键函数介绍:

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);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,648评论 0 3
  • FFmpeg 介绍 FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LG...
    Y了个J阅读 11,217评论 0 28
  • 写在前面 如果对FFmpeg有需要更多了解的请订阅我的专题:音视频专辑 3.1 FFmpeg 文件结构 libav...
    张芳涛阅读 2,546评论 0 21
  • ffmpeg是一个非常有用的命令行程序,它可以用来转码媒体文件。它是领先的多媒体框架FFmpeg的一部分,其有很多...
    城市之光阅读 6,726评论 3 6
  • 对于FFMPEG是只闻其名,不见其人,各个大厂比如QQ影音,Bilibili等等都是以它为基础的。(好多都是从雷神...
    猪_队友阅读 422评论 0 1