在ffmpeg中,网络视频流h264为什么默认的转为YUV而不是其他格式

news2024/11/16 8:46:48

在做网络视频的时候,有些视频的编程概念,早点知道,早点弄清楚会少走很多的弯路。对应视频的转码,传输,一开始如果直接跟着代码跑的话,很容易觉得自己都明白了,但是为什么这样做,好像也讲出去个一二三来。

比如:在ffmpeg中,网络视频流h264为什么默认的转为YUV而不是其他格式?

从这个问题开始,我们慢慢的把一些概念理清楚,这样一来,编程的时候就容易理解了。

什么是h264

也被称为AVC(高级视频编码),是一种视频压缩标准。这是一种高效的视频编码方法,可以在保持高质量的同时,大幅度减少所需的带宽和存储空间。H264编码的视频可以在各种设备上播放,包括电视、电脑、智能手机等。在视频处理中,H264用于压缩视频数据,使其更便于传输和存储。

什么是YUV

这是一种颜色编码系统,常用于视频系统。YUV模型定义了一个颜色空间,其中Y表示亮度(灰度),而U和V表示色度(色彩和饱和度)。这种颜色编码方式的优点是可以更有效地压缩颜色信息,因为人眼对亮度的敏感度远高于色度。在视频处理中,YUV通常用于在保留视觉质量的同时减少所需的带宽或存储。

还有一个概念那就是我们经常提到的RGB格式。

什么是RGB

RGB是一种加色模型,其中R代表红色,G代表绿色,B代表蓝色。RGB模型采用红、绿、蓝三种颜色的光以不同的比例混合,以产生其他颜色。RGB模型主要用于显示设备,如电脑屏幕、电视和手机等,因为这些设备通过发射红、绿、蓝三种颜色的光来显示图像。RGB模型的优点是可以表示大范围的颜色,并且直观易于理解。

可以这么说RGB,YUV是不同时代的产物,一开始我们在设计黑白电视机的时候,只要有灰度就能显示图片,图片知识黑白的而已,到了彩色电视以后,又引入了U和V这两个向量,颜色的问题也就兼容了。

到了LED的时代,采用红、绿、蓝三种颜色的光以不同的比例混合,以产生其他颜色,也就是RGB。

为什么H264编码通常解码为YUV格式,而不是RGB格式的

H264编码的视频通常首先解码为YUV格式,而不是RGB格式,这主要是由于以下几个原因:

  1. 压缩效率:YUV格式的颜色编码更适合于视频压缩。在YUV格式中,亮度信息(Y)和色度信息(UV)是分开的,这使得在压缩过程中可以对色度信息进行更大程度的压缩,因为人眼对亮度的敏感度远高于色度。这就意味着,在相同的视频质量下,YUV格式的视频数据通常比RGB格式的视频数据更小。

  2. 兼容性:许多视频设备和系统,包括电视和DVD播放器等,都使用YUV格式。因此,解码为YUV格式可以确保视频在这些设备和系统上的兼容性。

  3. 色彩空间转换:虽然H264编码的视频可以被解码为RGB格式,但这通常需要额外的色彩空间转换步骤。相比之下,直接解码为YUV格式则更为简单和高效。

因此,虽然H264编码的视频可以被解码为RGB格式,但由于压缩效率、兼容性和处理效率的考虑,通常首先解码为YUV格式。

在视频的传输中用的是yuv还是h264

在视频的传输中,通常使用的是H264格式。这是因为H264是一种高效的视频压缩标准,它可以在保持高质量的同时,大幅度减少所需的带宽和存储空间。由于其高效的压缩性能,H264已经成为网络视频和流媒体的主流编码格式。

然而,这并不意味着YUV在视频传输中没有用处。实际上,YUV是一种颜色编码系统,用于在视频处理中有效地压缩颜色信息。在视频被编码为H264格式之前,通常会先将其转换为YUV格式。

因此,虽然在视频传输中主要使用H264格式,但YUV格式在视频处理和编码的过程中仍然起着重要的作用。

利用ffmpeg,把h264转为YUV

以下是一个使用FFmpeg库的基本示例,它展示了如何打开一个H.264格式的视频文件,读取每一帧,并将其转换为YUV格式:

extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
}

int main() {
    // 注册所有的编解码器和格式
    av_register_all();

    // 打开视频文件
    AVFormatContext* formatContext = NULL;
    if (avformat_open_input(&formatContext, "a.h264", NULL, NULL) < 0) {
        // 错误处理...
    }

    // 查找视频流
    if (avformat_find_stream_info(formatContext, NULL) < 0) {
        // 错误处理...
    }
    int videoStreamIndex = -1;
    for (int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }
    if (videoStreamIndex == -1) {
        // 错误处理...
    }

    // 找到并打开解码器
    AVCodec* codec = avcodec_find_decoder(formatContext->streams[videoStreamIndex]->codecpar->codec_id);
    AVCodecContext* codecContext = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar);
    if (avcodec_open2(codecContext, codec, NULL) < 0) {
        // 错误处理...
    }

    // 读取和解码视频帧
    AVPacket packet;
    AVFrame* frame = av_frame_alloc();
    while (av_read_frame(formatContext, &packet) >= 0) {
        if (packet.stream_index == videoStreamIndex) {
            if (avcodec_send_packet(codecContext, &packet) < 0) {
                // 错误处理...
            }
            while (avcodec_receive_frame(codecContext, frame) == 0) {
                // 此时,frame包含YUV数据
                // ... 处理frame的数据 ...
            }
        }
        av_packet_unref(&packet);
    }

    // 释放资源
    av_frame_free(&frame);
    avcodec_close(codecContext);
    avcodec_free_context(&codecContext);
    avformat_close_input(&formatContext);

    return 0;
}

在这个示例中,我们首先打开一个视频文件,并查找视频流。然后,我们找到并打开适当的解码器。接着,我们读取和解码视频帧,每当我们收到一个新的帧时,我们就处理它的YUV数据。最后,我们释放所有的资源。

利用SDL 把视频显示出来

在SDL2中,可以直接把YUV格式的数据显示出来,而且也比较容易,代码如下:

AVPacket packet;
	AVFrame* frame = av_frame_alloc();
	while (av_read_frame(pFormatCtx, &packet) >= 0) {
		if (packet.stream_index == videoindex) {
			if (avcodec_send_packet(codecContext, &packet) < 0) {
				// 错误处理...
			}
			while (avcodec_receive_frame(codecContext, frame) == 0) {
				// 此时,frame包含YUV数据

				//开始显示
				SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
					frame->data[0], frame->linesize[0],
					frame->data[1], frame->linesize[1],
					frame->data[2], frame->linesize[2]);

				SDL_RenderClear(sdlRenderer);
				SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
				SDL_RenderPresent(sdlRenderer);
				//SDL End-----------------------
				//Delay 1000/60ms--假设每分钟60帧
				SDL_Delay(1000/60);
			}
			av_packet_unref(&packet);
		}
		
	}

显示的效果如下:
在这里插入图片描述
刚才我们说过,YUV其实可以不用UV通道,可以让他显示为黑白的视频。修改一下代码,把UV通道都赋值为128,就可以看到灰色的效果了。

代码修改如下:

				memset(frame->data[1], 128, frame->linesize[1] * frame->height / 2);
				memset(frame->data[2], 128, frame->linesize[2] * frame->height / 2);
				SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
					frame->data[0], frame->linesize[0],
					frame->data[1], frame->linesize[1],
					frame->data[2], frame->linesize[2]);

在这里插入图片描述
所有的代码都已在git上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1141180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用WebStorm创建和配置TypeScript项目

创建 这里我用的是WebStorm 2019.2.2版本 首先&#xff0c;创建一个空项目 File -> New -> Project->Empty Project生成配置文件 自动配置&#xff1a; 打开终端输入tsc --init&#xff0c;即可自动生成tsconfig.json文件 手动配置&#xff1a; 在项目根目录下新建一…

第四章 文件管理 八、文件保护

目录 一、口令保护 1、定义&#xff1a; 2、优点&#xff1a; 3、缺点: 二、加密保护 1、定义&#xff1a; 2、例子&#xff1a; 2、优点&#xff1a; 3、缺点: 三、访问控制 1、定义&#xff1a; 2、精简的访问控制表&#xff1a; &#xff08;1&#xff09;定义&a…

海南海口大型钢结构件3D扫描全尺寸三维测量平面度平行度检测-CASAIM中科广电

高精度三维扫描技术已经在大型工件制造领域发挥着重要作用&#xff0c;特别是在质量检测环节&#xff0c;高效、高精度&#xff0c;可以轻松实现全尺寸三维测量。本期&#xff0c;CASAIM要分享的应用是在大型钢结构件的关键部位尺寸及形位公差检测。 钢结构件&#xff0c;是将…

38 深度学习(二):tensorflow基础介绍

文章目录 tensorflow基础介绍基础张量自定义损失函数自定义模型和激活函数图函数&#xff08;略&#xff09;自动求导机制自定义fit tensorflow基础介绍 基础张量 import tensorflow as tf import numpy as np import pandas as pd# constant是常量张量 不能进行再次assign改…

【ETL工具】Datax-ETL-SqlServerToHDFS

&#x1f984; 个人主页——&#x1f390;个人主页 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; 感谢点赞和关注 &#xff0c;每天进步一点点&#xff01;加油&#xff01;&…

lazada获得lazada商品详情 API 返回值说明

item_get-获得lazada商品详情 lazada.item_get 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;获取key和secret接入secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_sear…

德思特新闻 | 走进德思特——通过创新帮助客户成功

文章来源&#xff1a;德思特测试测量 阅读原文&#xff1a;德思特新闻 | 走进德思特——通过创新帮助客户成功 走进德思特 2023年上半年&#xff0c;ChatGPT红遍全球&#xff0c;人工智能、B5G/6G、物联网、云计算、软件自动化等新兴技术的快速发展进一步推动科技行业的复苏…

vue核心面试题汇总【查缺补漏】

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 很喜欢‘万变不离其宗’这句话&#xff0c;希望在不断的思考和总结中找到Vue中的宗&#xff0c;来解答面试官抛出的…

gd32部分映射1/2,完全映射,备用功能选择等

一、重映射与部分映射问题 参考相应用户手册&#xff1b; 打开&#xff1a;I/O 重映射功能和调试配置&#xff1b; AFIO 端口配置寄存器 0&#xff08;AFIO_PCF0&#xff09;&#xff1b; AFIO 端口配置寄存器 1&#xff08;AFIO_PCF1&#xff09;&#xff1b; 【e.g】以定时器…

Java练习题2021-4

"某游戏公司设计了一个奖励活动&#xff0c;给N个用户(1≤N≤10^7)连续编号为1到N&#xff0c;依据用户的编号S发放奖励。 发放奖励规则为&#xff1a; 公司随机设定三个非零正整数x&#xff0c;y&#xff0c;z。 如果S同时是x、y的倍数&#xff0c;奖励2张卡片&#xff1…

QCI利用量子计算为飞行汽车提供优化飞行路径和改进设计的功能

​&#xff08;图片来源&#xff1a;网络&#xff09; 长期以来&#xff0c;飞行汽车和量子计算机一直是“未来技术”的简写&#xff0c;它们将彻底改变交通世界。预计到2032年&#xff0c;量子计算的市场价值将达到1700亿美元&#xff0c;当前有很多实际用例已经证明了它的价…

如何用 Zabbix 监控 Radius 服务?

网管小贾 / sysadm.cc Radius 对于搞系统的小伙伴们来说应该并不陌生&#xff0c;它是提供身份认证的服务程序。 Radius 应用广泛&#xff0c;最简单的场景之一就是无线连接&#xff0c;使用用户名密码或者证书等方式通过它的验证后无线网络连接就可以建立起来。 如此重要的一…

1496. 判断路径是否相交

1496. 判断路径是否相交 java代码&#xff1a; class Solution {public boolean isPathCrossing(String path) {int x 0;int y 0;HashSet<String> hashSet new HashSet<>();hashSet.add("0-0");for (int i 0; i < path.length(); i) {switch (pa…

Vue-cli 搭建 SPA 项目,Vue 项目结构说明,开发示例,以及如何修改端口号,install 命令中的 -g,-S,-D 参数,嵌套路由,package.json 详解

目录 1. vue-cli安装 1.1 安装前提 1.2 什么是vue-cli 1.3 安装vue-cli 2. 使用vue-cli构建项目 2.1 使用脚手架创建项目骨架 2.2 到新建项目目录&#xff0c;安装需要的模块 2.3 如何修改端口号 2.4 添加element-ui模块 2.5 package.json详解 3. install命令中的-g…

FLStudio21完整版编曲软件多少钱?要不要购买

水果&#xff0c;全称Fruity Loop Studio&#xff0c;简称FL Studio。是一款全能的音乐制作软件&#xff0c;经过二十多年的演化更迭&#xff0c;其各项功能非常的先进。其开创性的Pat\song模式&#xff0c;也为初学者的学习提供了便利。那么水果音乐制作软件需要多少钱呢&…

修复VS2015没有代码提示的问题【已解决】

问题描述 在Visual Studio 中编写代码时&#xff0c;发现使用库函数的时候&#xff0c;在类对象后输入点后&#xff0c;并没有出现类对应的成员信息的提示。 解决过程 1&#xff09;方法1&#xff1a; 百度“vs 没有代码提示”&#xff0c;搜索解决方案。 方案1&#xff1…

高级路由配置

目录 路由协议认证 Ripv2的认证配置 OSPF认证 BGP认证 OSPF特殊区域 BGP的选路规则 路由策略&#xff08;route-policy和filter-policy&#xff09; IP-Prefix List:前缀列表 Filter-Policy 路由引入&#xff08;import-route&#xff09; Filter-policy和route-pol…

『 基础算法题解 』之双指针(下)

文章目录 和为S的两个数题目解析算法原理代码 三数之和题目解析算法原理代码 四数之和题目解析算法原理代码 和为S的两个数 题目解析 【题目链接】 该题目的原题为和为s的两个数: 即给定一组升序数据(数组price),并给出一个变量target,要求找出和为target的两个数; 算法原理…

第4关:书籍排序

题目&#xff1a; C&C结构体 (educoder.net) 思路&#xff1a; 1.字符串字典序排序---> 利用string.h里面的strcmp&#xff0c;由其返回值确定两字符串大小。&#xff08;pstrcmp(a,b)&#xff0c;若p>1&#xff0c;则a字典序大于b。&#xff09; 2.当不能定义字…

Java练习题2021-1

"从大于等于N的正整数里找到一个最小的数M&#xff0c;使之满足&#xff1a; M和M的逆序数&#xff08;如1230的逆序数为321&#xff09;的差的绝对值为一个[100000,200000]区间内的值。 输入说明&#xff1a;起始数字N&#xff1b; 输出说明&#xff1a;找到的第一个符合…