热门标签 | 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


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 本文详细介绍了如何在 Windows 环境下使用 node-gyp 工具进行 Node.js 本地扩展的编译和配置,涵盖从环境搭建到代码实现的全过程。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文详细介绍了Python编程语言的学习路径,涵盖基础语法、常用组件、开发工具、数据库管理、Web服务开发、大数据分析、人工智能、爬虫开发及办公自动化等多个方向。通过系统化的学习计划,帮助初学者快速掌握Python的核心技能。 ... [详细]
  • 深入解析Nginx中的Location指令及其属性
    本文将详细探讨Nginx配置文件中关键的location指令,包括其三种匹配方式(精准匹配、普通匹配和正则匹配),以及如何在实际应用中灵活运用这些匹配规则。此外,还将介绍location下的重要子元素如root、alias和proxy_pass,并解释相关参数的使用方法。 ... [详细]
  • 本文详细介绍了如何在PHP中进行数组删除、清空等操作,并提供了在Visual Studio Code中创建PHP文件的步骤。 ... [详细]
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社区 版权所有