【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )

简介: 【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )

文章目录

I . FFMPEG 获取 AVPacket 数据前置操作

II . FFMPEG 获取 AVPacket 数据流程

III . FFMPEG AVPacket 结构体

IV . AVPacket 数据读取流程

V . FFMPEG 初始化 AVPacket 数据包 av_packet_alloc ( )

VI . FFMPEG 读取 AVPacket 数据 av_read_frame ( )

VII . FFMPEG 获取 AVPacket 数据流程 代码示例



I . FFMPEG 获取 AVPacket 数据前置操作


FFMPEG 获取 AVPacket 数据前置操作 :



① FFMPEG 初始化 : 参考博客 【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )


② FFMPEG 获取 AVStream 音视频流 : 参考博客 【Android FFMPEG 开发】FFMPEG 获取 AVStream 音视频流 ( AVFormatContext 结构体 | 获取音视频流信息 | 获取音视频流个数 | 获取音视频流 )


③ FFMPEG 获取 AVCodec 编解码器 : 参考博客 【Android FFMPEG 开发】FFMPEG 获取编解码器 ( 获取编解码参数 | 查找编解码器 | 获取编解码器上下文 | 设置上下文参数 | 打开编解码器 )




II . FFMPEG 获取 AVPacket 数据流程


FFMPEG 获取 AVPacket 数据流程 :



〇 前置操作 : FFMPEG 环境初始化 , 获取 AVStream 音视频流 , 获取 AVCodec 编解码器 , 然后才能进行下面的操作 ;



① 初始化 AVPacket 空数据包 : av_packet_alloc ( )


AVPacket *avPacket = av_packet_alloc();



② 读取 AVPacket 数据 : av_read_frame ( AVFormatContext *s , AVPacket *pkt )


int read_frame_result = av_read_frame(formatContext, avPacket);




III . FFMPEG AVPacket 结构体


1 . AVPacket 结构体 : 该结构体用于封装被编码压缩的数据 , 不能直接使用 , 需要解码后才能进行音频视频播放 ;


typedef struct AVPacket {
  ...
} AVPacket;



2 . AVPacket 存储数据 : AVPacket 存放编码后的音视频数据的 , 获取该数据包后 , 需要对该数据进行解码 , 解码后将数据存放在 AVFrame 中 ;



3 . 编码前后数据存放 : AVPacket 是编码后的数据 , AVFrame 是编码前的数据 ;




IV . AVPacket 数据读取流程


1 . 读取音视频流数据到 AVPacket 中 : 首先要在外部声明 AVPacket * 结构体指针 , 并为其初始化 , 然后调用 av_read_frame ( ) 方法 , 将已经初始化好内存的 AVPacket * 结构体指针 传给上述方法 , FFMPEG 将在 av_read_frame ( ) 方法中读取数据 , 并存储到堆内存中的 AVPacket 结构体中 ;



2 . AVPacket 的内存初始化和释放 :



① AVPacket 初始化 : 调用 av_packet_alloc ( ) 方法初始化内存 ;


② AVPacket 释放 : 调用 av_packet_free ( ) 释放内存 ;




V . FFMPEG 初始化 AVPacket 数据包 av_packet_alloc ( )


1 . av_packet_alloc ( ) 函数原型 : 在堆内存中为 AVPacket 分配内存 , 并为 AVPacket 结构体各个字段设置默认值 ;


① 返回值 : 返回一个 AVPacket * 结构体指针 , 如果内存分配失败 , 就会返回 NULL ;


/**
 * Allocate an AVPacket and set its fields to default values.  The resulting
 * struct must be freed using av_packet_free().
 *
 * @return An AVPacket filled with default values or NULL on failure.
 *
 * @note this only allocates the AVPacket itself, not the data buffers. Those
 * must be allocated through other means such as av_new_packet.
 *
 * @see av_new_packet
 */
AVPacket *av_packet_alloc(void);


2 . 代码示例 :


//读取数据包
// AVPacket 存放编码后的音视频数据的 , 获取该数据包后 , 需要对该数据进行解码 , 解码后将数据存放在 AVFrame 中
// AVPacket 是编码后的数据 , AVFrame 是编码前的数据
//创建 AVPacket 空数据包
AVPacket *avPacket = av_packet_alloc();



VI . FFMPEG 读取 AVPacket 数据 av_read_frame ( )


1 . av_read_frame ( ) 函数原型 : 获取音视频流的下一帧数据 ;



① AVFormatContext *s 参数 : 该参数中存储了音视频流格式相关信息 , 该参数是在之前使用 avformat_find_stream_info ( ) 方法获取的 ;


② AVPacket *pkt 参数 : 传入该结构体指针 , 在方法中会按照 AVFormatContext *s 信息读取一帧音视频数据 , 并将该数据存储到 AVPacket 结构体中 ;


③ int 返回值 : 返回 0 代表读取一帧数据 ( 音频 / 视频 ) 成功 , < 0 说明获取数据失败 ;


/**
 * Return the next frame of a stream.
 * This function returns what is stored in the file, and does not validate
 * that what is there are valid frames for the decoder. It will split what is
 * stored in the file into frames and return one for each call. It will not
 * omit invalid data between valid frames so as to give the decoder the maximum
 * information possible for decoding.
 *
 * If pkt->buf is NULL, then the packet is valid until the next
 * av_read_frame() or until avformat_close_input(). Otherwise the packet
 * is valid indefinitely. In both cases the packet must be freed with
 * av_packet_unref when it is no longer needed. For video, the packet contains
 * exactly one frame. For audio, it contains an integer number of frames if each
 * frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames
 * have a variable size (e.g. MPEG audio), then it contains one frame.
 *
 * pkt->pts, pkt->dts and pkt->duration are always set to correct
 * values in AVStream.time_base units (and guessed if the format cannot
 * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format
 * has B-frames, so it is better to rely on pkt->dts if you do not
 * decompress the payload.
 *
 * @return 0 if OK, < 0 on error or end of file
 */
int av_read_frame(AVFormatContext *s, AVPacket *pkt);



2 . FFMPEG 读取 AVPacket 数据 代码示例 :


/*
    读取数据包 , 并存储到 AVPacket 数据包中
    参数分析 : 一维指针 与 二维指针 参数分析
      ① 注意 : 第二个参数是 AVPacket * 类型的 , 那么传入 AVPacket *avPacket 变量
            不能修改 avPacket 指针的指向 , 即该指针指向的结构体不能改变
            只能修改 avPacket 指向的结构体中的元素的值
              因此 , 传入的 avPacket 结构体指针必须先进行初始化 , 然后再传入
                  av_read_frame 函数内 , 没有修改 AVPacket *avPacket 的值 , 但是修改了结构体中元素的值
      ② 与此相对应的是 avformat_open_input 方法 , 传入 AVFormatContext ** 二维指针
          传入的的 AVFormatContext ** 是没有经过初始化的 , 连内存都没有分配
          在 avformat_open_input 方法中创建并初始化 AVFormatContext * 结构体指针
          然后将该指针地址赋值给 AVFormatContext **
              avformat_open_input 函数内修改了 AVFormatContext ** 参数的值
    返回值 0 说明读取成功 , 小于 0 说明读取失败 , 或者 读取完毕
 */
int read_frame_result = av_read_frame(formatContext, avPacket);



VII . FFMPEG 获取 AVPacket 数据流程 代码示例


//读取数据包
// AVPacket 存放编码后的音视频数据的 , 获取该数据包后 , 需要对该数据进行解码 , 解码后将数据存放在 AVFrame 中
// AVPacket 是编码后的数据 , AVFrame 是编码前的数据
//创建 AVPacket 空数据包
AVPacket *avPacket = av_packet_alloc();
/*
    读取数据包 , 并存储到 AVPacket 数据包中
    参数分析 : 一维指针 与 二维指针 参数分析
      ① 注意 : 第二个参数是 AVPacket * 类型的 , 那么传入 AVPacket *avPacket 变量
            不能修改 avPacket 指针的指向 , 即该指针指向的结构体不能改变
            只能修改 avPacket 指向的结构体中的元素的值
              因此 , 传入的 avPacket 结构体指针必须先进行初始化 , 然后再传入
                  av_read_frame 函数内 , 没有修改 AVPacket *avPacket 的值 , 但是修改了结构体中元素的值
      ② 与此相对应的是 avformat_open_input 方法 , 传入 AVFormatContext ** 二维指针
          传入的的 AVFormatContext ** 是没有经过初始化的 , 连内存都没有分配
          在 avformat_open_input 方法中创建并初始化 AVFormatContext * 结构体指针
          然后将该指针地址赋值给 AVFormatContext **
              avformat_open_input 函数内修改了 AVFormatContext ** 参数的值
    返回值 0 说明读取成功 , 小于 0 说明读取失败 , 或者 读取完毕
 */
int read_frame_result = av_read_frame(formatContext, avPacket);


目录
相关文章
|
7月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
746 4
|
21天前
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
266 2
|
4月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
291 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
10月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
186 1
|
8月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
262 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
8月前
|
API
FFmpeg中AVPacket、AVFrame结构的基本使用
FFmpeg中AVPacket和AVFrame结构的内存分配、释放和引用计数处理,以及如何避免内存泄漏。
203 3
|
8月前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
325 0
|
9月前
|
Android开发 计算机视觉 C++
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架
音视频编程对许多程序员来说是一片充满挑战的领域,但借助如OpenCV、LearnOpenGL、FFmpeg、OBS Studio及VLC media player等强大的开源工具,可以降低入门门槛。这些框架不仅覆盖了计算机视觉、图形渲染,还包括多媒体处理与直播技术,通过多种编程语言如Python、C++的应用,使得音视频开发更为便捷。例如,OpenCV支持跨平台的视觉应用开发,FFmpeg则擅长多媒体文件的处理与转换,而VLC media player则是验证音视频文件质量的有效工具。
205 0
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架
|
10月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
208 1
|
9月前
用ffmpeg提取合并音视频
用ffmpeg提取合并音视频

热门文章

最新文章