【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )

举报
韩曙亮 发表于 2022/01/11 01:24:51 2022/01/11
【摘要】 文章目录 I . FFMPEG 初始化流程II . FFMPEG 网络初始化 avformat_network_init()III . FFMPEG 打开媒体地址 avformat_open_in...



I . FFMPEG 初始化流程



FFMPEG 初始化流程 : FFMPEG 执行任何操作前 , 都需要初始化一些环境 , 及相关数据参数 ;


① 网络初始化 : avformat_network_init()

int avformat_network_init(void);

  
 
  • 1

② 打开媒体 ( 音视频 ) 地址 : avformat_open_input()

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

  
 
  • 1

③ 查找 ( 音 / 视频 ) 流 : avformat_find_stream_info()

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

  
 
  • 1

④ 正式操作 : 对上述查找到的 音 / 视频 流进行操作 ;



II . FFMPEG 网络初始化 avformat_network_init()



调用 avformat_network_init() 函数进行网络初始化


1 . avformat_network_init() 函数作用 : 初始化网络 , 默认状态下 , FFMPEG 是不允许联网的 , 必须调用该函数 , 初始化网络后 FFMPEG 才能进行联网 ;


2 . avformat_network_init() 函数原型 :

/**
 * Do global initialization of network libraries. This is optional,
 * and not recommended anymore.
 *
 * This functions only exists to work around thread-safety issues
 * with older GnuTLS or OpenSSL libraries. If libavformat is linked
 * to newer versions of those libraries, or if you do not use them,
 * calling this function is unnecessary. Otherwise, you need to call
 * this function before any other threads using them are started.
 *
 * This function will be deprecated once support for older GnuTLS and
 * OpenSSL libraries is removed, and this function has no purpose
 * anymore.
 */
int avformat_network_init(void);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3 . 使用示例 :

    /*
     * 初始化网络 :
     *      默认状态下 , FFMPEG 是不允许联网的
     *      必须调用该函数 , 初始化网络后 FFMPEG 才能进行联网
     */
    avformat_network_init();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


III . FFMPEG 打开媒体地址 avformat_open_input()



调用 avformat_open_input() 函数打开音视频地址 ( 文件地址 / 网络地址 )


1 . avformat_open_input() 函数作用 : 播放一个音视频多媒体文件之前 , 首先要打开该文件 ; 文件的地址类型可以是文件路径地址 , 也可以是网络地址 ;


2 . avformat_open_input() 函数原型 :


① AVFormatContext **ps 参数 : 封装了文件格式相关信息的结构体 , 如视频宽高 , 音频采样率等信息 ; 该参数是 二级指针 , 意味着在方法中会修改该指针的指向 , 该参数的实际作用是当做返回值用的 ;

② const char *url 参数 : 视频资源地址, 文件地址 / 网络链接 ;

③ int 返回值 : 返回 0 , 代表打开成功 , 否则失败 ; 失败的情况列举 , 文件路径错误 , 网络错误 ;

/**
 * Open an input stream and read the header. The codecs are not opened.
 * The stream must be closed with avformat_close_input().
 *
 * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
 *           May be a pointer to NULL, in which case an AVFormatContext is allocated by this
 *           function and written into ps.
 *           Note that a user-supplied AVFormatContext will be freed on failure.
 * @param url URL of the stream to open.
 * @param fmt If non-NULL, this parameter forces a specific input format.
 *            Otherwise the format is autodetected.
 * @param options  A dictionary filled with AVFormatContext and demuxer-private options.
 *                 On return this parameter will be destroyed and replaced with a dict containing
 *                 options that were not found. May be NULL.
 *
 * @return 0 on success, a negative AVERROR on failure.
 *
 * @note If you want to use custom IO, preallocate the format context and set its pb field.
 */
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3 . 使用示例 :

    //1 . 打开音视频地址 ( 播放文件前 , 需要先将文件打开 )
    //      地址类型 : ① 文件类型 , ② 音视频流
    //  参数解析 :
    //      AVFormatContext **ps :  封装了文件格式相关信息的结构体 , 如视频宽高 , 音频采样率等信息 ;
    //                              该参数是 二级指针 , 意味着在方法中会修改该指针的指向 ,
    //                              该参数的实际作用是当做返回值用的
    //      const char *url :   视频资源地址, 文件地址 / 网络链接
    //  返回值说明 : 返回 0 , 代表打开成功 , 否则失败
    //              失败的情况 : 文件路径错误 , 网络错误
    //int avformat_open_input(AVFormatContext **ps, const char *url,
    //                          AVInputFormat *fmt, AVDictionary **options);
    formatContext = 0;
    int open_result = avformat_open_input(&formatContext, dataSource, 0, 0);

    //如果返回值不是 0 , 说明打开视频文件失败 , 需要将错误信息在 Java 层进行提示
    //  这里将错误码返回到 Java 层显示即可
    if(open_result != 0){
        __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "打开媒体失败 : %s", av_err2str(open_result));
        callHelper->onError(pid, 0);
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20


IV . FFMPEG 获取音 / 视频流信息 avformat_find_stream_info()



调用 avformat_find_stream_info() 函数获取音视频流信息


1 . avformat_find_stream_info() 函数作用 : 打开音视频文件成功后 , 从该地址中获取对应的音视频流 , 获取的流赋值给了 AVFormatContext* 结构体的 nb_streams 成员 ;


2 . avformat_find_stream_info() 函数原型 :


① AVFormatContext **ps 参数 : 封装了文件格式相关信息的结构体 , 如视频宽高 , 音频采样率等信息 ; 该参数是 二级指针 , 意味着在方法中会修改该指针的指向 , 该参数的实际作用是当做返回值用的 ;

调用该方法后 , AVFormatContext 结构体的 nb_streams 元素就有值了 ;

③ int 返回值 : 返回值 >= 0 , 代表打开成功 , 否则失败 ;

/**
 * Read packets of a media file to get stream information. This
 * is useful for file formats with no headers such as MPEG. This
 * function also computes the real framerate in case of MPEG-2 repeat
 * frame mode.
 * The logical file position is not changed by this function;
 * examined packets may be buffered for later processing.
 *
 * @param ic media file handle
 * @param options  If non-NULL, an ic.nb_streams long array of pointers to
 *                 dictionaries, where i-th member contains options for
 *                 codec corresponding to i-th stream.
 *                 On return each dictionary will be filled with options that were not found.
 * @return >=0 if OK, AVERROR_xxx on error
 *
 * @note this function isn't guaranteed to open all the codecs, so
 *       options being non-empty at return is a perfectly normal behavior.
 *
 * @todo Let the user decide somehow what information is needed so that
 *       we do not waste time getting stuff the user does not need.
 */
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3 . 使用示例 :

    //2 . 查找媒体 地址 对应的音视频流 ( 给 AVFormatContext* 成员赋值 )
    //      方法原型 : int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
    //      调用该方法后 , AVFormatContext 结构体的 nb_streams 元素就有值了 ,
    //      该值代表了音视频流 AVStream 个数
    int find_result = avformat_find_stream_info(formatContext, 0);

    //如果返回值 < 0 , 说明查找音视频流失败 , 需要将错误信息在 Java 层进行提示
    //  这里将错误码返回到 Java 层显示即可
    if(find_result < 0){
        __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "查找媒体流失败 : %s", av_err2str(find_result));
        callHelper->onError(pid, 1);
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12


V . FFMPEG 初始化部分代码示例



    /*
     * 初始化网络 :
     *      默认状态下 , FFMPEG 是不允许联网的
     *      必须调用该函数 , 初始化网络后 FFMPEG 才能进行联网
     */
    avformat_network_init();


    //0 . 注册组件
    //      如果是 4.x 之前的版本需要执行该步骤
    //      4.x 及之后的版本 , 就没有该步骤了
    //av_register_all();

    //1 . 打开音视频地址 ( 播放文件前 , 需要先将文件打开 )
    //      地址类型 : ① 文件类型 , ② 音视频流
    //  参数解析 :
    //      AVFormatContext **ps :  封装了文件格式相关信息的结构体 , 如视频宽高 , 音频采样率等信息 ;
    //                              该参数是 二级指针 , 意味着在方法中会修改该指针的指向 ,
    //                              该参数的实际作用是当做返回值用的
    //      const char *url :   视频资源地址, 文件地址 / 网络链接
    //  返回值说明 : 返回 0 , 代表打开成功 , 否则失败
    //              失败的情况 : 文件路径错误 , 网络错误
    //int avformat_open_input(AVFormatContext **ps, const char *url,
    //                          AVInputFormat *fmt, AVDictionary **options);
    formatContext = 0;
    int open_result = avformat_open_input(&formatContext, dataSource, 0, 0);

    //如果返回值不是 0 , 说明打开视频文件失败 , 需要将错误信息在 Java 层进行提示
    //  这里将错误码返回到 Java 层显示即可
    if(open_result != 0){
        __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "打开媒体失败 : %s", av_err2str(open_result));
        callHelper->onError(pid, 0);
    }



    //2 . 查找媒体 地址 对应的音视频流 ( 给 AVFormatContext* 成员赋值 )
    //      方法原型 : int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
    //      调用该方法后 , AVFormatContext 结构体的 nb_streams 元素就有值了 ,
    //      该值代表了音视频流 AVStream 个数
    int find_result = avformat_find_stream_info(formatContext, 0);

    //如果返回值 < 0 , 说明查找音视频流失败 , 需要将错误信息在 Java 层进行提示
    //  这里将错误码返回到 Java 层显示即可
    if(find_result < 0){
        __android_log_print(ANDROID_LOG_ERROR , "FFMPEG" , "查找媒体流失败 : %s", av_err2str(find_result));
        callHelper->onError(pid, 1);
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/104636151

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。