android平台下基于ffmpeg的swscale模块实现对YUV和RGB数据进行转换

FFmpeg解码提速之libyuv FFmpeg解码,提速之libyuv 阅读详情

音视频实践学习

概述

其实如果对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 = avformat_alloc_context();

    // 3.打开一个输入文件
    if (avformat_open_input(&pFormatCtx, videoPath, NULL, NULL) != 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 = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoIndex = i;
            break;
        }
    if (videoIndex == -1) {
        LOGE("Could not find a video stream");
        goto end_line;
    }
    // 5.查找解码器
    pCodec = avcodec_find_decoder(pFormatCtx->streams[videoIndex]->codecpar->codec_id);
    if (pCodec == NULL) {
        LOGE("Could not find Codec");
        goto end_line;
    }

    // 6.配置解码器
    pCodecCtx = avcodec_alloc_context3(pCodec);
    avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoIndex]->codecpar);
    pCodecCtx->thread_count = 1;

    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        LOGE("Could not open codec");
        goto end_line;
    }

    pFrame = av_frame_alloc();
    vPacket = (AVPacket *) av_malloc(sizeof(AVPacket));
    pFrameYUV = av_frame_alloc();


    bufferSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,
                                          1);
    out_buffer = (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 = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
    out_buffer = (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 = sws_getContext(pCodecCtx->width,
                             pCodecCtx->height,
                             pCodecCtx->pix_fmt,
                             pCodecCtx->width,
                             pCodecCtx->height,
                             AV_PIX_FMT_YUV420P, //AV_PIX_FMT_RGB24
                             SWS_BICUBIC,
                             NULL, NULL, NULL);

    outputFile = fopen(outputPath, "wb+");

    while (av_read_frame(pFormatCtx, vPacket) >= 0) {
        if (vPacket->stream_index == videoIndex) {
            if (avcodec_send_packet(pCodecCtx, vPacket) != 0) {
                return -1;
            }
            while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {

                sws_scale(sws_ctx, (const uint8_t *const *) pFrame->data, pFrame->linesize,
                          0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

                //YUV420P
                fwrite(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 != NULL) {
        fclose(outputFile);
        outputFile = 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文件,同步到本地电脑上,使用ffplay可以直接播放:

ffplay -f rawvideo -video_size 480x960 output.yuv

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

参考:
https://blog.youkuaiyun.com/leixiaohua1020/article/details/14215391

从硬件加速视角解析YUV与RGB转换:FFmpeg的swscale实战指南 本文深入探讨了如何利用FFmpeg的swscale模块实现YUV与RGB色彩空间的高效转换,特别关注硬件加速技术的应用。通过分析NVIDIA CUDA、Intel Quick Sync等硬件平台优化策略,提供实战代码示例和性能调优技巧,帮助开发者应对4K/8K视频处理中的性能挑战。 阅读详情

相关推荐

别再混淆了!I420、NV12、NV21这些YUV格式到底怎么选?附FFmpeg实战代码

本文深入解析I420、NV12、NV21等YUV格式的核心差异与应用场景,帮助开发者根据平台需求(如Android的NV21与iOS的NV12)和编码器要求(如H.264的I420)做出最佳选择。附FFmpeg实战代码,涵盖格式转换技巧与硬件加速方案,助你优化视频处理流程。

weixin_30835649的博客 524

FFmpeg4.3系列之54:Android+FFmpeg播放器与ij

FFmpeg系列之54【FFmpeg第四季Android音视频专题之4】Android+FFmpeg播放器与ijkplayer二次开发 我将带领大家来学习Android +FFmpeg 实现音视频的解码与播放,并学习ijkplayer二次开发。具体内容包括:NDK与ANativeWindow绘图、bmp格式与压缩原理、OpenGL.ES打造YUV播放器、颜色空间RGB与YUV底层原理详解、Android使用libyuv开源库、FFmpeg命令行处理PCM、Android.OPENSL.ES及PCM实战、Android+FFmpeg解码并播放音频、Android+FFmpeg解码并播放视频、Android播放器之ijkplayer二次开发等。 --------------------------------------------------------作为音视频开发小白,需要从最基本的图片和PCM开始,循序渐进,逐步到后期的编解码、软编硬编、视频特效、直播应用等。大家在学习过程中需要多动手,多思考,建议先系统的看一遍视频,然后第二遍跟着一起练习,然后再总结分析提升。

FFmpeg之二 摄像头录制保存视频, API编解码从理论到实战

摄像头录制保存视频, API编解码从理论到实战,手把手教学

薛瑄的博客 2084

ffmpeg 视频编码二(基于 libswscale 转换视频)

前言 看了上篇文章的小伙伴应该都知道了编码的一些问题了,这篇文章我们就来解决它。 要解决上篇文章所述的问题,我们先了解一个扩展库 libswscale ,Libswscale里面实现了各种图像像素格式的转换(例如YUV与RGB之间的转换);以及图像大小缩放的功能(例如640x360拉伸为1280x720);以及前后图像的滤波处理(例如高斯模糊)。基于此,我们就可以解决我们上篇文章遇到的问题了。 libswscale的使用 要使用libswscale,我们必定要对齐有所了解,其核心函数主要有三个,下面分别介绍

qq_35543489的博客 2608

Android平台C++媒体播放器开发:从FFmpeg解码到音视频同步实战

在移动应用开发中,高性能音视频处理是核心技术领域之一,其底层实现通常依赖于C/C++语言以保证执行效率。其核心原理涉及媒体数据的解封装、解码、渲染与同步流程,通过FFmpeg等开源库实现跨格式编解码,结合多线程架构管理数据流。这项技术的工程价值在于能够为短视频、直播、游戏等场景提供稳定高效的播放能力,解决音画同步、低延迟等关键问题。本文以Android平台为例,详细解析如何利用NDK、OpenGL ES和OpenSL ES构建本地播放器,涵盖FFmpeg集成、线程模型设计及音视频同步策略,帮助开发者深入理解

weixin_30918633的博客 416

Android-音视频学习系列-(四)-一键编译-32-64-位-FFmpeg-4-2-2

bin/sh#帮组选项#标准选项#–disable 代表关闭状态;–enable 代表开启状态#我们最终编译好的动态静态库位置,必须设置#开启静态库#关闭动态库#可以优化库的大小#我们不需要使用程序,不需要在Windows中执行,某.exe程序,我们只需要在代码中使用 [此命令操作的是下面三项]#使用FFmpeg命令#播放器#模块选项。

2401_84544434的博客 786

FFMPEG 之视频播放

先看界面效果,虽然有点low,但是效果实现了 一、实现原理 1、使用ffmpeg解码视频 2、然后使用libyuv播放解码的视频 二、实现 1、先看目录结构 2、ffmpeg编译以及引用,在之前的篇章已经说过了,不知道得可以看看之前的文章 3、编译libyuv       1、首先在https://chromium.googlesource.com/external/lib

万小凡的专栏 8143

FFmpeg之libyuv使用(十五)

1.下载、编译、安装libyuv # git clone https://github.com/lemenkov/libyuv.git # cd libyuv # mkdir build # cd build # cmake .. # make -j4 # sudo make install 2.demo.c

Android系统攻城狮 1719

android FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24…)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法。 swscale主要用于在2个AVFrame之间进行转换。 下面来看一个视频解码的简单例子,这个程序完成了对"北京移动开发者大会茶歇视频2.flv"(其实就是优酷上的一个普通视频)的解码工作,并将解码后的数据保存为原始数据...

安卓兼职framework和app工程师的博客 828

NDK开发——FFmpeg实现视频转YUV、视频转RGB显示、音频转PCM、音频播放、音视频同步

NDK开发——FFmpeg实现视频转YUV、视频转RGB显示、音频转PCM、音频播放、音视频同步

医疗影像处理实战:如何用Slicer和Mimics将.nii.gz文件转为.ply格式(附避坑指南)

本文详细介绍了利用3D Slicer和Materialise Mimics软件,将医学影像中常见的.nii.gz格式文件转换为通用三维网格.ply格式的完整实战流程。文章重点分享了从数据分割、DICOM序列导出到高质量网格生成的核心步骤与关键参数设置,并提供了针对常见问题的避坑指南,旨在帮助医学影像研究者和工程师高效完成从体数据到三维模型的关键转换。

weixin_28304023的博客 103

【亲测免费】 libyuv 安卓 Android 编译好的 SO 库文件及源代码

本仓库提供最新版 libyuv 的编译好的 SO 库文件及源代码,适用于安卓平台。具体包括以下内容: - **arm64-v8a** 平台的动态库文件 - **armeabi-v7a** 平台的动态库文件 - **x86** 平台的动态库文件 - **x86_64** 平台的动态库文件 这些库文件可以直接在安卓项目中使用,无需额外编译。libyuv 是一个高效的 YUV 转 RGB 库,其转换

gitblog_09750的博客 1092

S7-200 SMART Modbus RTU从站配置与调试实战指南

本文提供了一份详细的S7-200 SMART PLC配置为Modbus RTU从站的实战指南。内容涵盖从硬件基础、软件准备、指令库调用、核心编程到地址映射与调试排错的完整流程。重点解析了MBUS_INIT与MBUS_SLAVE指令的关键参数配置,并深入探讨了Modbus地址与PLC内部V存储区的对应关系,帮助工程师快速打通通讯链路,实现与上位机、触摸屏等主站设备的稳定数据交互。

potato的博客 752

高性能图像处理利器:libyuv 安卓 SO 库文件及源代码推荐

libyuv 是一个专为安卓平台设计的高效 YUV 转 RGB 库。本仓库提供了最新版 libyuv 的编译好的 SO 库文件及源代码,适用于安卓平台的多种架构,包括 **arm64-v8a**、**armeabi-v7a**、**x86** 和 **x86_64**。这些库文件可以直接集成到安卓项目中,无需额外编译,极大地简化了开发流程。 ## 项目技术分析 libyuv 的核心优势在于其高

gitblog_09759的博客 1128

晶晨S905L3S/S905L3SB芯片刷机实战:BL加载工具与线刷固件全解析

本文针对晶晨S905L3S/S905L3SB芯片电视盒子刷机时常见的2%失败问题,提供了两种核心解决方案。一是使用已集成特殊通信协议的专用版USB Burning Tool(如V2.2.5/V2.2.7),二是采用旧版工具配合独立的BootLoader加载工具。文章详细解析了两种方案的原理、操作步骤、固件选择及常见问题排查,旨在帮助用户成功完成刷机,让老旧设备焕发新生。

weixin_29238147的博客 1107

30、航空公司调度问题的数学模型解析

本文详细解析了航空公司调度问题中的核心数学模型,包括航班时刻表生成、机组人员排班和飞机调度的建模方法与求解技术。通过定义变量、约束条件及目标函数,结合线性规划、整数规划等方法,帮助航空公司实现高效调度。文章还探讨了模型的优化策略、简化方法以及实际应用案例,为提升航空运营效率提供了理论支持和实践指导。

beer8的博客 259

H264转成RGB24格式-2016.01.21

H264转成RGB24格式-2016.01.21 #include "libavcodec/avcodec.h" #include "libswscale/swscale.h" #include "libavutil/opt.h" #include "liba...

dianli2014的专栏 613

Android CCodec (十七) 硬件解码调用分析-1(基于V4l2)

简单的分析V4L2DecodeComponent和其相关内容,后续针对解码调用单独分析。

给大佬递杯卡布奇诺的博客 6593

android 在surface上显示YUV 笔记

基于android的远程视频监控系统——:http://www.apkbus.com/forum.php?mod=viewthread&amp;amp;tid=57452 如何在native C显示YUV420格式图像?:http://www.eoeandroid.com/thread-52488-1-1.html Android视频渲染,YUV转RGB:http://www.icodelogic.c...

mmdev 460

【红外技术】DDE算法:HE在红外图像可视化上的应用(附源码)

并且数据一般是以 8 的整数倍的位宽在电子系统中应用,因此大多数的显示器的显示位宽为 8bit,共 256 个灰阶。为了使红外图像可视化,因此需要一种“数据压缩”技术,还需要既可能的不丢失原始图像信息。HE后的图像直方图分布比较均匀离散,图像对比度好。但是HE算法只是适用某些图像,它是将灰度集中区域进行拉伸得到,也会放大该集中区域的噪声,它是一种“不公平”的映射。以下是红外细节增强算法的演示,很明显右边的图像,展现了更多的图像细节,对于小目标的观测非常友好。文章已于2019-12-02修改。

sunwindl91181的博客 911

【YOLOv8系列】在Windows上离线搭建YOLOv8运行环境

我们都知道,通过 pip安装YOLOv8是非常方便的,但是有时候网络环境受到限制,比如公司的工作站(无法连接网络)或者机房的教学机器等等,只能通过离线的方式安装YOLOv8;今天就来记录一下离线搭建YOLOv8运行环境的过程。并记录了遇到的问题及解决过程。

AnChenliang_1002的博客 2004

Android 音视频之FFmpeg

FFmpeg介绍 FFmpeg是一套可以用来记录、处理数字音频、视频,并将其转换为流的开源框架,采用LPL或GPL许可证,提供了录制、转换以及流化音视频的完整解决方案。它的可移植性或者说跨平台特性非常强大。 默认的编译会生成4个可执行文件和8个静态库。 可执行文件包括用于转码、推流、Dump媒体文件的ffmpeg、用于播放媒体文件的ffplay、用于获取媒体文件信息的ffprobe,以及作为简...

ArvinFei的博客 978

Token 费用爆炸?教你用 Semantic Cache(语义缓存)把 API 成本降低 80%

本文介绍了语义缓存(Semantic Cache)技术在大模型应用中的关键作用。传统Redis缓存基于精确匹配,无法处理用户提问的语义相似性,导致重复调用昂贵的LLM API。语义缓存通过将问题向量化并在向量空间中进行相似度匹配,可识别30%-50%的重复提问,直接返回历史答案。文章详细解析了技术原理(Embedding+向量搜索)、架构设计,并提供了基于Python和ChromaDB的50行核心实现代码。同时指出了生产环境中的三大挑战:阈值设定、隐私保护和多轮对话处理,并给出相应解决方案。该技术能以极低成

BUG猿的博客 1056

音视频篇 - FFmpeg 的介绍和使用

本文章是阅读《音视频开发进阶指南基于android与ios平台的实践》一书的学习笔记。第三章:FFMpeg 的介绍和使用。

u014294681的博客 2973

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

android 渲染bgr24,H264转成RGB24格式-2016.01.21

#include "libavcodec/avcodec.h"#include"libswscale/swscale.h"#include"libavutil/opt.h"#include"libavutil/imgutils.h"#include#include#include#includetypedefenum{FALSE= 0, TRUE = 1,} C_BOOL;typedef unsi...

weixin_32075745的博客 462

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

FFmpeg 播放器视频渲染优化

所以,OpenGLRender 视频渲染器要兼容 YUV420P、 YUV420SP 以及 RGBA 格式,需要创建 3 个纹理存储待渲染的数据,渲染 YUV420P 格式的图像需要用到 3 个纹理,渲染 YUV420SP 格式的图像只需用到 2 个纹理即可,而渲染 RGBA 格式图像只需一个纹理。YUV420P 格式的图像在内存中有 3 个平面,YUV420SP (NV21、NV12)格式的图像在内存中有 2 个平面,而 RGBA 格式的图像只有一个平面。对应的顶点着色器和片段着色器,其中重要的是,

金戈鐡馬 705

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: android平台下基于ffmpeg实现对相机预览截图的功能(NV21数据编码为JPEG文件)
下一篇: android平台下基于MediaRecorder和AudioRecord实现录制AAC、PCM音频数据
handy周
handy周 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄14年 507粉丝 240原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值