门户网站的含义,qq邮箱企业邮箱注册,jsp网站开发学习心得,手机版网站优化在做网络视频的时候#xff0c;有些视频的编程概念#xff0c;早点知道#xff0c;早点弄清楚会少走很多的弯路。对应视频的转码#xff0c;传输#xff0c;一开始如果直接跟着代码跑的话#xff0c;很容易觉得自己都明白了#xff0c;但是为什么这样做#xff0c;好像…在做网络视频的时候有些视频的编程概念早点知道早点弄清楚会少走很多的弯路。对应视频的转码传输一开始如果直接跟着代码跑的话很容易觉得自己都明白了但是为什么这样做好像也讲出去个一二三来。
比如在ffmpeg中网络视频流h264为什么默认的转为YUV而不是其他格式
从这个问题开始我们慢慢的把一些概念理清楚这样一来编程的时候就容易理解了。
什么是h264
也被称为AVC高级视频编码是一种视频压缩标准。这是一种高效的视频编码方法可以在保持高质量的同时大幅度减少所需的带宽和存储空间。H264编码的视频可以在各种设备上播放包括电视、电脑、智能手机等。在视频处理中H264用于压缩视频数据使其更便于传输和存储。
什么是YUV
这是一种颜色编码系统常用于视频系统。YUV模型定义了一个颜色空间其中Y表示亮度灰度而U和V表示色度色彩和饱和度。这种颜色编码方式的优点是可以更有效地压缩颜色信息因为人眼对亮度的敏感度远高于色度。在视频处理中YUV通常用于在保留视觉质量的同时减少所需的带宽或存储。
还有一个概念那就是我们经常提到的RGB格式。
什么是RGB
RGB是一种加色模型其中R代表红色G代表绿色B代表蓝色。RGB模型采用红、绿、蓝三种颜色的光以不同的比例混合以产生其他颜色。RGB模型主要用于显示设备如电脑屏幕、电视和手机等因为这些设备通过发射红、绿、蓝三种颜色的光来显示图像。RGB模型的优点是可以表示大范围的颜色并且直观易于理解。
可以这么说RGBYUV是不同时代的产物一开始我们在设计黑白电视机的时候只要有灰度就能显示图片图片知识黑白的而已到了彩色电视以后又引入了U和V这两个向量颜色的问题也就兼容了。
到了LED的时代采用红、绿、蓝三种颜色的光以不同的比例混合以产生其他颜色也就是RGB。
为什么H264编码通常解码为YUV格式而不是RGB格式的
H264编码的视频通常首先解码为YUV格式而不是RGB格式这主要是由于以下几个原因 压缩效率YUV格式的颜色编码更适合于视频压缩。在YUV格式中亮度信息Y和色度信息UV是分开的这使得在压缩过程中可以对色度信息进行更大程度的压缩因为人眼对亮度的敏感度远高于色度。这就意味着在相同的视频质量下YUV格式的视频数据通常比RGB格式的视频数据更小。 兼容性许多视频设备和系统包括电视和DVD播放器等都使用YUV格式。因此解码为YUV格式可以确保视频在这些设备和系统上的兼容性。 色彩空间转换虽然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上。