热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转

本文探讨了在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转的技术细节。通过详细分析Swscale的工作原理和实际应用,展示了如何在Android环境中高效地进行图像格式转换。此外,还介绍了FFmpeg的全平台编译过程,包括x264和fdk-aac的集成,并在Ubuntu系统中配置Nginx和Nginx-RTMP-Module以支持直播推流服务。这些技术的结合为音视频处理提供了强大的支持。

音视频实践学习


  • android全平台编译ffmpeg以及x264与fdk-aac实践
  • ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器
  • android全平台编译ffmpeg合并为单个库实践
  • android-studio使用cmake编译ffmpeg实践
  • android全平台下基于ffmpeg解码MP4视频文件为YUV文件
  • android全平台编译ffmpeg支持命令行实践
  • android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器
  • android平台下音频编码之编译LAME库转码PCM为MP3
  • ubuntu平台下编译vlc-android视频播放器实践
  • 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
  • 图解RGB565、RGB555、RGB16、RGB24、RGB32、ARGB32等格式的区别
  • YUV420P、YUV420SP、NV12、NV21和RGB互相转换并存储为JPEG以及PNG图片
  • android全平台编译libyuv库实现YUV和RGB的转换
  • android平台下基于ffmpeg对相机采集的NV21数据编码为MP4视频文件
  • android平台下基于ffmpeg采集Camera数据编码成H.264推流到RTMP服务器
  • android平台下基于ffmpeg和ANativeWindow实现简单的视频播放器
  • android平台下基于ffmpeg实现对相机预览截图的功能(NV21数据编码为JPEG文件)
  • android平台下基于ffmpeg的swscale模块实现对YUV和RGB数据进行转换

概述

其实如果对YUV和RGB数据进行转换,更推荐使用libyuv库进行转换,效率更高一些,今天记录一下ffmpeg库自带的swscale模块进行转码工作。

环境配置

操作系统:ubuntu 16.05
ndk版本:android-ndk-r16b
ffmpeg版本:ffmpeg-3.3.8

流程分析

工程实践

核心的转码实现:Transform


#include "native_swscale.h"
#include "logger.h"int NativeSwscale::Transform(const char *videoPath, const char *outputPath) {// 1.注册所有组件av_register_all();// 2.创建AVFormatContext结构体pFormatCtx &#61; avformat_alloc_context();// 3.打开一个输入文件if (avformat_open_input(&pFormatCtx, videoPath, NULL, NULL) !&#61; 0) {LOGE("Could not open input stream");goto end_line;}// 4.获取媒体的信息if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {LOGE("Could not find stream information");goto end_line;}//获取视频轨的下标for (int i &#61; 0; i < pFormatCtx->nb_streams; i&#43;&#43;)if (pFormatCtx->streams[i]->codecpar->codec_type &#61;&#61; AVMEDIA_TYPE_VIDEO) {videoIndex &#61; i;break;}if (videoIndex &#61;&#61; -1) {LOGE("Could not find a video stream");goto end_line;}// 5.查找解码器pCodec &#61; avcodec_find_decoder(pFormatCtx->streams[videoIndex]->codecpar->codec_id);if (pCodec &#61;&#61; NULL) {LOGE("Could not find Codec");goto end_line;}// 6.配置解码器pCodecCtx &#61; avcodec_alloc_context3(pCodec);avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoIndex]->codecpar);pCodecCtx->thread_count &#61; 1;if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {LOGE("Could not open codec");goto end_line;}pFrame &#61; av_frame_alloc();vPacket &#61; (AVPacket *) av_malloc(sizeof(AVPacket));pFrameYUV &#61; av_frame_alloc();bufferSize &#61; av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,1);out_buffer &#61; (uint8_t *) av_malloc(bufferSize * sizeof(uint8_t));av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height, 1);//RGB24转换/*bufferSize &#61; av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);out_buffer &#61; (uint8_t *) av_malloc(bufferSize * sizeof(uint8_t));av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height, 1);*///转换sws_ctx &#61; sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,AV_PIX_FMT_YUV420P, //AV_PIX_FMT_RGB24SWS_BICUBIC,NULL, NULL, NULL);outputFile &#61; fopen(outputPath, "wb&#43;");while (av_read_frame(pFormatCtx, vPacket) >&#61; 0) {if (vPacket->stream_index &#61;&#61; videoIndex) {if (avcodec_send_packet(pCodecCtx, vPacket) !&#61; 0) {return -1;}while (avcodec_receive_frame(pCodecCtx, pFrame) &#61;&#61; 0) {sws_scale(sws_ctx, (const uint8_t *const *) pFrame->data, pFrame->linesize,0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);//YUV420Pfwrite(pFrameYUV->data[0], (pCodecCtx->width) * (pCodecCtx->height), 1, outputFile);fwrite(pFrameYUV->data[1], (pCodecCtx->width) * (pCodecCtx->height) / 4, 1,outputFile);fwrite(pFrameYUV->data[2], (pCodecCtx->width) * (pCodecCtx->height) / 4, 1,outputFile);//RGB24//fwrite(pFrameYUV->data[0], (pCodecCtx->width) * (pCodecCtx->height) * 3, 1, outputFile);//UYVY//fwrite(pFrameYUV->data[0],(pCodecCtx->width)*(pCodecCtx->height),2,outputFile);}}av_packet_unref(vPacket);}if (outputFile !&#61; NULL) {fclose(outputFile);outputFile &#61; NULL;}sws_freeContext(sws_ctx);end_line:avcodec_close(pCodecCtx);avcodec_free_context(&pCodecCtx);av_free(pFrame);av_free(pFrameYUV);avformat_close_input(&pFormatCtx);avformat_free_context(pFormatCtx);return 0;
}

最终输出一个output.yuv文件&#xff0c;同步到本地电脑上&#xff0c;使用ffplay可以直接播放&#xff1a;

ffplay -f rawvideo -video_size 480x960 output.yuv

项目地址&#xff1a;ffmpeg-single-swscale
https://github.com/byhook/ffmpeg4android

参考&#xff1a;
https://blog.csdn.net/leixiaohua1020/article/details/14215391


推荐阅读
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 尽管使用TensorFlow和PyTorch等成熟框架可以显著降低实现递归神经网络(RNN)的门槛,但对于初学者来说,理解其底层原理至关重要。本文将引导您使用NumPy从头构建一个用于自然语言处理(NLP)的RNN模型。 ... [详细]
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • python的交互模式怎么输出名文汉字[python常见问题]
    在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就进入到Python交互模式,它的提示符是>>>,此时我们可以使用print() ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 深入解析:手把手教你构建决策树算法
    本文详细介绍了机器学习中广泛应用的决策树算法,通过天气数据集的实例演示了ID3和CART算法的手动推导过程。文章长度约2000字,建议阅读时间5分钟。 ... [详细]
  • 本文详细介绍了如何在 Linux 平台上安装和配置 PostgreSQL 数据库。通过访问官方资源并遵循特定的操作步骤,用户可以在不同发行版(如 Ubuntu 和 Red Hat)上顺利完成 PostgreSQL 的安装。 ... [详细]
  • 深入解析Nginx中的Location指令及其属性
    本文将详细探讨Nginx配置文件中关键的location指令,包括其三种匹配方式(精准匹配、普通匹配和正则匹配),以及如何在实际应用中灵活运用这些匹配规则。此外,还将介绍location下的重要子元素如root、alias和proxy_pass,并解释相关参数的使用方法。 ... [详细]
  • Nginx 反向代理与负载均衡实验
    本实验旨在通过配置 Nginx 实现反向代理和负载均衡,确保从北京本地代理服务器访问上海的 Web 服务器时,能够依次显示红、黄、绿三种颜色页面以验证负载均衡效果。 ... [详细]
author-avatar
卟可爱頹廢
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有