文章目录

  • I . FFMPEG AVFrame 图像数据帧处理 前置操作
  • II . FFMPEG 解码 AVPacket 数据到 AVFrame 流程
  • III. FFMPEG 解码前后的图像格式
  • IV . FFMPEG 获取 SwsContext
  • V . FFMPEG 初始化图像数据存储内存
  • VI . FFMPEG 初图像格式转换
  • VII . FFMPEG AVFrame 图像格式转换 YUV -> RGBA 代码示例

I . FFMPEG AVFrame 图像数据帧处理 前置操作


FFMPEG 解码 AVPacket 数据到 AVFrame 数据前置操作 :

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

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

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

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

⑤ FFMPEG 解码 AVPacket 数据到 AVFrame : 参考博客 【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )

II . FFMPEG 解码 AVPacket 数据到 AVFrame 流程


FFMPEG 解码 AVPacket 数据到 AVFrame 流程 :

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

① 获取 SwsContext : sws_getContext ( )

SwsContext *swsContext = sws_getContext(//源图像的 宽 , 高 , 图像像素格式avCodecContext->width, avCodecContext->height, avCodecContext->pix_fmt,//目标图像 大小不变 , 不进行缩放操作 , 只将像素格式设置成 RGBA 格式的avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,//使用的转换算法 , FFMPEG 提供了许多转换算法 , 有快速的 , 有高质量的 , 需要自己测试SWS_BILINEAR,//源图像滤镜 , 这里传 NULL 即可0,//目标图像滤镜 , 这里传 NULL 即可0,//额外参数 , 这里传 NULL 即可0);

② 初始化图像数据存储空间 : av_image_alloc ( )

av_image_alloc(dst_data, dst_linesize,avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,1);

③ 转换图像格式 : sws_scale ( )

sws_scale(//SwsContext *swsContext 转换上下文swsContext,//要转换的数据内容avFrame->data,//数据中每行的字节长度avFrame->linesize,0,avFrame->height,//转换后目标图像数据存放在这里dst_data,//转换后的目标图像行数dst_linesize);

III. FFMPEG 解码前后的图像格式


AVPacket 数据解码后的数据存储在 AVFrame 结构体中 , 如果是视频数据 , 那么存储的是一帧图像 , 图像的像素格式是 YUV 格式的 , 一般 Android 中绘制需要使用 ARGB 的像素格式 , 这里需要将图像的存储格式由 YUV 格式转为 ARGB 格式 ;

IV . FFMPEG 获取 SwsContext


1 . SwsContext 结构体 : 转换图像格式 , 首先要获取 SwsContext 结构体指针 , 在该 SwsContext 结构体中封装了图像转换相关的参数信息 , 如 源图像 目标图像的宽高 , 像素格式信息等 ; 调用 sws_getContext ( ) 方法可以获取 SwsContext * 结构体指针 ;

2 . SwsContext ( ) 函数原型 : 为 SwsContext 结构体分配内存 , 并返回其结构体指针 ;

① int srcW 参数 : 源图像的宽度 ;

② int srcH 参数 : 源图像的高度 ;

③ enum AVPixelFormat srcFormat 参数 : 源图像的像素格式 ;

④ int dstW 参数 : 目标图像的宽度 ;

⑤ int dstH 参数 : 目标图像的高度 ;

⑥ enum AVPixelFormat dstFormat 参数 : 目标图像的像素格式 ;

⑦ int flags 参数 : 使用的转换算法 , 可以选择高速度 , 或者高质量等参数 ;

⑧ SwsFilter *srcFilter 参数 : 源图像滤镜 ;

⑨ SwsFilter *dstFilter 参数 : 目标图像滤镜 ;

⑩ const double *param 参数 : 额外参数 ;

/*** Allocate and return an SwsContext. You need it to perform* scaling/conversion operations using sws_scale().** @param srcW the width of the source image* @param srcH the height of the source image* @param srcFormat the source image format* @param dstW the width of the destination image* @param dstH the height of the destination image* @param dstFormat the destination image format* @param flags specify which algorithm and options to use for rescaling* @param param extra parameters to tune the used scaler*              For SWS_BICUBIC param[0] and [1] tune the shape of the basis*              function, param[0] tunes f(1) and param[1] f´(1)*              For SWS_GAUSS param[0] tunes the exponent and thus cutoff*              frequency*              For SWS_LANCZOS param[0] tunes the width of the window function* @return a pointer to an allocated context, or NULL in case of error* @note this function is to be removed after a saner alternative is*       written*/
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,int dstW, int dstH, enum AVPixelFormat dstFormat,int flags, SwsFilter *srcFilter,SwsFilter *dstFilter, const double *param);

3 . 获取 SwsContext 代码示例 :

    SwsContext *swsContext = sws_getContext(//源图像的 宽 , 高 , 图像像素格式avCodecContext->width, avCodecContext->height, avCodecContext->pix_fmt,//目标图像 大小不变 , 不进行缩放操作 , 只将像素格式设置成 RGBA 格式的avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,//使用的转换算法 , FFMPEG 提供了许多转换算法 , 有快速的 , 有高质量的 , 需要自己测试SWS_BILINEAR,//源图像滤镜 , 这里传 NULL 即可0,//目标图像滤镜 , 这里传 NULL 即可0,//额外参数 , 这里传 NULL 即可0);

V . FFMPEG 初始化图像数据存储内存


1 . 图像数据保存 : 需要两个变量来进行存储 , 一个是指针 , 指向一块内存 , 该内存中存储实际的图像数据 , 一个是 int 数值 , 存储该内存中存储了多少数据 ;

① 指针 : 将图像数据保存到 uint8_t *dst_data[4] 指针数组中的指针元素指向的内存中 ;

② 行数 : int dst_linesize[4] 中存储其行数 , 代表了上面指针指向的内存每行存储了多少数据 ;

2 . 图像数据指针的操作 :

① 初始化 : 这个内存需要用专门的函数 av_image_alloc ( ) 进行初始化 ;

② 释放 : 这个指针需要使用专门的函数 void av_freep(void *ptr) 进行释放 ;

3 . av_image_alloc ( ) 函数原型 : 根据图像的宽高 , 像素格式 , 为 相应的 指向图像数据的指针 和 行数 进行初始化 ;

① uint8_t *pointers[4] 参数 : 指向图像数据的指针 , 这是四个指针 , 这里只是用了一个 , 也就是第一个 ;

② int linesizes[4] 参数 : 存储每个图像数据存储的数据行数 ;

③ int w 参数 : 图像的宽度 ;

④ int h 参数 : 图像的高度 ;

⑤ enum AVPixelFormat pix_fmt : 图像的像素格式 , ARGB 格式的 ;

⑥ int align 参数 : 设置 1 即可 ;

/*** Allocate an image with size w and h and pixel format pix_fmt, and* fill pointers and linesizes accordingly.* The allocated image buffer has to be freed by using* av_freep(&pointers[0]).** @param align the value to use for buffer size alignment* @return the size in bytes required for the image buffer, a negative* error code in case of failure*/
int av_image_alloc(uint8_t *pointers[4], int linesizes[4],int w, int h, enum AVPixelFormat pix_fmt, int align);

4 . av_image_alloc ( ) 代码示例 :

//指针数组 , 数组中存放的是指针
uint8_t *dst_data[4];//普通的 int 数组
int dst_linesize[4];//初始化 dst_data 和 dst_linesize , 为其申请内存 , 注意使用完毕后需要释放内存
av_image_alloc(dst_data, dst_linesize,avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,1);

VI . FFMPEG 初图像格式转换


1 . 准备工作完毕 : 转换使用的上下文 SwsContext , 转换后的数据存储 指针 和 行数 , 准备就绪后 , 可以开始转换 AVFrame 中的 YUV 像素格式的图像为 RGBA 像素格式 ;

2 . 转换使用方法 : 调用 sws_scale ( ) 方法 , 执行转换操作 ;

3 . sws_scale ( ) 函数原型 : 转换图像像素格式 ;

① struct SwsContext *c 参数 : 转换上下文 ;

② const uint8_t *const srcSlice[] 参数 : 源图像数据指针 ;

③ const int srcStride[] 参数 : 源图像每行有多少个数据 ;

④ int srcSliceY 参数 : 源图像数据数组处理的索引值 , 从 0 开始计数 , 一般是 0 ;

⑤ int srcSliceH 参数 : 源图像的高度 , 即有多少行数据 ;

⑥ uint8_t *const dst[] 参数 : 图像数组指针数组 ;

⑦ const int dstStride[] 参数 : 图像数据每行的数据个数 ;

/*** Scale the image slice in srcSlice and put the resulting scaled* slice in the image in dst. A slice is a sequence of consecutive* rows in an image.** Slices have to be provided in sequential order, either in* top-bottom or bottom-top order. If slices are provided in* non-sequential order the behavior of the function is undefined.** @param c         the scaling context previously created with*                  sws_getContext()* @param srcSlice  the array containing the pointers to the planes of*                  the source slice* @param srcStride the array containing the strides for each plane of*                  the source image* @param srcSliceY the position in the source image of the slice to*                  process, that is the number (counted starting from*                  zero) in the image of the first row of the slice* @param srcSliceH the height of the source slice, that is the number*                  of rows in the slice* @param dst       the array containing the pointers to the planes of*                  the destination image* @param dstStride the array containing the strides for each plane of*                  the destination image* @return          the height of the output slice*/
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],const int srcStride[], int srcSliceY, int srcSliceH,uint8_t *const dst[], const int dstStride[]);

4 . sws_scale ( ) 使用示例 :

sws_scale(//SwsContext *swsContext 转换上下文swsContext,//要转换的数据内容avFrame->data,//数据中每行的字节长度avFrame->linesize,0,avFrame->height,//转换后目标图像数据存放在这里dst_data,//转换后的目标图像行数dst_linesize);

VII . FFMPEG AVFrame 图像格式转换 YUV -> RGBA 代码示例


//1 . 获取转换上下文
SwsContext *swsContext = sws_getContext(//源图像的 宽 , 高 , 图像像素格式avCodecContext->width, avCodecContext->height, avCodecContext->pix_fmt,//目标图像 大小不变 , 不进行缩放操作 , 只将像素格式设置成 RGBA 格式的avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,//使用的转换算法 , FFMPEG 提供了许多转换算法 , 有快速的 , 有高质量的 , 需要自己测试SWS_BILINEAR,//源图像滤镜 , 这里传 NULL 即可0,//目标图像滤镜 , 这里传 NULL 即可0,//额外参数 , 这里传 NULL 即可0);//2 . 初始化图像存储内存//指针数组 , 数组中存放的是指针
uint8_t *dst_data[4];//普通的 int 数组
int dst_linesize[4];//初始化 dst_data 和 dst_linesize , 为其申请内存 , 注意使用完毕后需要释放内存
av_image_alloc(dst_data, dst_linesize,avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,1);//3 . 格式转换
sws_scale(//SwsContext *swsContext 转换上下文swsContext,//要转换的数据内容avFrame->data,//数据中每行的字节长度avFrame->linesize,0,avFrame->height,//转换后目标图像数据存放在这里dst_data,//转换后的目标图像行数dst_linesize);

【Android FFMPEG 开发】FFMPEG AVFrame 图像格式转换 YUV - RGBA ( 获取 SwsContext | 初始化图像数据存储内存 | 图像格式转换 )相关推荐

  1. 【Android FFMPEG 开发】FFMPEG ANativeWindow 原生绘制 ( 设置 ANativeWindow 缓冲区属性 | 获取绘制缓冲区 | 填充数据到缓冲区 | 启动绘制 )

    文章目录 I . FFMPEG ANativeWindow 原生绘制 前置操作 II . FFMPEG 原生绘制流程 III . 设置 ANativeWindow 绘制窗口属性 ANativeWind ...

  2. 使用FFMpeg API 获取摄像头的图像数据

    文章目录 1. 获取摄像头的信息 2. 打开并初始化摄像头 3. 获取摄像头数据及渲染 摄像头是我们比较常用的外设,很多场景我们都会用到摄像头.比如视频直播.视频监控等各个领域都会用到摄像头.摄像头图 ...

  3. 【SemiDrive源码分析】【MailBox核间通信】46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化、数据收发流程分析

    [SemiDrive源码分析][MailBox核间通信]46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化.数据收发流程分析 三. rp ...

  4. FFmpeg开发实战(五):bmp转换为jpeg格式图像

    文章目录 1. bmp结构 2. bgr24转yuv420p 3. yuv420转jpeg 4. 下载 本文介绍了将bmp格式图像转换为jpeg格式图像的方法,附有详细的代码和图像示例. 1. bmp ...

  5. Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/123536470 红胖子(红模仿)的博文大全:开发技术集 ...

  6. python 读取图片成为一维数组_在OpenCV里图像数据与一维数组转换

    通过读取文件之后,生成的图像数据一般是二维或三维数组,每个数组元素是8位字节大小.有时候从网络里接收到一串数据,它是字节顺序的,比如有30000个字节,想要把它转换为300X100的图像大小,这个怎么 ...

  7. 在OpenCV里图像数据与一维数组转换

    通过读取文件之后,生成的图像数据一般是二维或三维数组,每个数组元素是8位字节大小.有时候从网络里接收到一串数据,它是字节顺序的,比如有30000个字节,想要把它转换为300X100的图像大小,这个怎么 ...

  8. 【Android FFMPEG 开发】OpenSLES 播放音频 ( 创建引擎 | 输出混音设置 | 配置输入输出 | 创建播放器 | 获取播放/队列接口 | 回调函数 | 开始播放 | 激活回调 )

    文章目录 I . FFMPEG 播放视频流程 II . OpenSLES 播放音频流程 III . OpenSLES 播放参考 Google 官方示例 IV . OpenSL ES 播放代码 ( 详细 ...

  9. 【Android FFMPEG 开发】FFMPEG ANativeWindow 原生绘制 ( Java 层获取 Surface | 传递画布到本地 | 创建 ANativeWindow )

    文章目录 I . FFMPEG ANativeWindow 原生绘制 II . FFMPEG 原生绘制流程 III . Java 层获取 Surface 画布 IV . 传递 Surface 画布到 ...

最新文章

  1. android getChildAt(index)返回null问题解决方法
  2. C++——拷贝构造函数
  3. Codeforces Round #741 (Div. 2)
  4. 日常小记录json文件(json.load()、json.loads()、json.dump()、json.dumps())
  5. Javascript 脚本错误.
  6. PHP留言并展示_留言页面展示功能
  7. 【观点讨论与支撑】科研学习的过程真的是枯燥的乏味的吗?
  8. Unity插件-HighlightingSystem(边缘光)
  9. 不用找,你想要的魏体字体素材都在这里
  10. 【Hexo】hexo在文章中添加图片
  11. FF系列重要Staff全列表 (转自天幻网)
  12. ubuntu20.04中安装划词翻译_支持语音录入翻译的小爱同学鼠标让智能设备控制一手掌握...
  13. win10安装Hive3.0.0
  14. screen 使用命令
  15. 关于微信表情及输入法emoji显示问题解决方案
  16. 一般服务器监控什么项目,服务器中需要监控的项目
  17. Python文件处理os模块介绍 -*- Python基础知识12 -*-
  18. java 截取字符串第一个字符
  19. 【有趣的Python小程序】Python多个简单上手的库制作WalkLattice 走格子游戏 (思路篇)下
  20. ekho tts 下载_TTS技术简单介绍和Ekho(余音)TTS的安装与编程 | 学步园

热门文章

  1. CCNA课堂练习一:路由器链路备份功能
  2. Python模块EasyGui专题学习
  3. 笔试题118-130
  4. 读书方法(如果努力有用的话,那还要天才干什么!)
  5. Android 动态Tab分页效果实现
  6. 2.1.2监测当前打印机状态
  7. 关于错误 openssl/ssl.h:没有那个文件或目录的解决办法
  8. 2017年6月21号课堂笔记
  9. getBoundingClientRect()方法
  10. snakebar 的使用