(一)视频定义(什么是视频)

FFmpeg学习(四)视频基础

(二)图像

FFmpeg学习(四)视频基础

1.像素:图像由像素组成(如下图图片中的一个个小格子)。

FFmpeg学习(四)视频基础

对于每个像素,还有位深的概念:用多少个位来表示位深。类似于音频中的采样大小

FFmpeg学习(四)视频基础

RGB888:对于R、G、B中每个元素占8位

RGBA:同上,多了一个A(透明度)

2.RGB:每个像素是由RGB三元素组成;如下图格子表示一个像素,内部由RGB(三个发光二极管)组成。

FFmpeg学习(四)视频基础FFmpeg学习(四)视频基础

通过RGB(三个发光二极管不同亮度组成)可以组合成多种色彩:

FFmpeg学习(四)视频基础

3.分辨率:用来表示图像在X、Y轴上各有多少个像素点。

(三)屏幕显示器

1.显示器和图像都具有像素!!!

FFmpeg学习(四)视频基础

对于屏幕而言,每一个像素如下所示:

FFmpeg学习(四)视频基础

根据图像的数据,来控制屏幕中每一个像素点的发光二极管的强度。从而实现不同颜色点,拼接为最终图像!! 

FFmpeg学习(四)视频基础

2.RGB的色彩问题(部分情况使用的BGR顺序,使得与显示器的驱动程序处理顺序不一致,导致图像渲染出错

FFmpeg学习(四)视频基础

3.屏幕指标

FFmpeg学习(四)视频基础

PPI:每英寸下的像素数 
DPI:每英寸下的点数
基本上两者相等,极少情况下DPI每个点中存在多个像素
PPI > 300 :视网膜级别(人眼无法区别是由像素组成,认为是一整块图像)

(四)码流的计算

FFmpeg学习(四)视频基础

1.分辨率(清晰度)

FFmpeg学习(四)视频基础

常见的视频宽高比是16:9,部分老式显示器可能是4:3;如果一个视频的宽高比不是这两种,则需要进行转换。
对于360P,16:9中是指高360P,宽640P

2.帧率(平滑、流畅度)

FFmpeg学习(四)视频基础

对于直播系统中,为了减少所占码流的大小,通常采用15帧/S;
录课:30帧/S
视频播放60帧/S

3.未编码视频的RGB码流

FFmpeg学习(四)视频基础

其中3Byte表示一个像素RGB所占大小

(五)图像的显示(图像和显示器分辨率不一致情况)

FFmpeg学习(四)视频基础

二:YUV了解

各种格式解析:https://www.fourcc.org/rgb.php

(一)什么是YUV(有了RGB图像之后,为什么还需要YUV?)

由电视系统发展而来,逐步从黑白--->彩色;YUV可以兼容这两种模式。当获取Y信号之后就可以正常的进行播放,此时颜色为黑白(黑白电视机可以播放)。UV用于描述影像的色彩和饱和度(彩色电视机播放需要)。最标准YUV格式为YUV4:2:0

FFmpeg学习(四)视频基础

在DVD、摄像机、数字电视等消费类视频产品中,常用的色彩编码方案是YCbCr,其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。

人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

1.YUV图像各个分量

YUV原始图像:

FFmpeg学习(四)视频基础

YUV图像的Y分量(只有明亮度、没有色彩和饱和度):

FFmpeg学习(四)视频基础

YUV图像的U分量(只有Cb分量,图片蓝色分量):

FFmpeg学习(四)视频基础

YUV图像的V分量(只有Cr分量,图片红色分量):

FFmpeg学习(四)视频基础

只有在电视中使用了YUV格式,在手机、屏幕、显示器中使用RGB格式,所以YUV显示在屏幕需要进行转换!

2.RGB与YUV的关系

FFmpeg学习(四)视频基础

RGB转YUV:

FFmpeg学习(四)视频基础

YUV转RGB:

FFmpeg学习(四)视频基础

3.YUV常见格式

FFmpeg学习(四)视频基础

YUV4:44 一个Y元素对应一个U元素对应一个V元素,对于1280×720图像,数据量为:1280×720×3---其中3同RGB888一致,表示3个字节(24位)
YUV4:22 对于每一个横行,隔一列有一个UV,数据量为1280×720×1+2×1280×720/2 = 1280×720×2--- ×1表示Y占1字节,/2是对于UV来说是每隔一列才有一个UV
YUV4:20 最标准,最广泛; 隔行分U或者V分量,隔列分是否有UV分量;数据量为1280×720×1+2×1280×720/4 = 1280×720×1.5
各个格式详细见下面图片!!!

YUV4:2:0

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础

对于YUV4:2:0而言满足下面的计算:

FFmpeg学习(四)视频基础

YUV4:2:0优点:

1.YUV兼容以前的图像
2.相比较RGB而言,数据量减少1半,存储更加具有优势!

补充:对齐知识!!!!

对于已经对齐的分辨率如:1280*720,640*480这样的分辨率它的YUV420P数据格式是完全对齐(16位对齐)

而像176*144这样的size它的YUV420P不是16位对齐,需要补空白位(0补齐),使得176*144这样的size能16位对齐。

YUV4:2:2

FFmpeg学习(四)视频基础

此格式的打包格式为,YUYV YUYV YUYV ……(YUYV422格式);此格式的存储格式为:首先全是Y,然后全是U,最后全是V。

FFmpeg学习(四)视频基础

YUV4:4:4

FFmpeg学习(四)视频基础

更多格式见:https://blog.csdn.net/cgwang_1580/article/details/79595958

(二)YUV4:2:0存储格式

YUV数据是分层存储的,所以可以更加方便的与黑白电视机相兼容,只需要读取前面的Y数据即可,后面的UV数据舍弃即可。对于彩色电视机,将后面的UV数据一块读取。
4:2:0,是指4个Y对应纵向1个U,1个V;如下图(色彩对应)

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础 

不同系统下,存储格式可能不同:比如IOS使用YV12,android使用NV21

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础

YUV4:2:0 码流计算:

FFmpeg学习(四)视频基础

(三)YUV命令行采集数据

原始mp4参数:

FFmpeg学习(四)视频基础

1.根据参数进行命令行采集YUV数据

ffmpeg -i gfxm.mp4 -an -c:v rawvideo -pix_fmt yuv420p out.yuv

FFmpeg学习(四)视频基础

ffplay -pix_fmt yuv420p -s 864*486 out.yuv   #-s是说明播放时的分辨率 -pix_fmt指定格式 如果两个参数不一致,会导致播放出现花屏等问题

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础

播放YUV图像的Y分量(其他分量也可以播放):

ffplay -pix_fmt yuv420p -s 864*486 -vf extractplanes='y' out.yuv    #-vf 表示滤波器,vf属于简单滤波

FFmpeg学习(四)视频基础

提取单独分量:

ffmpeg -i gfxm.mp4 -filter_complex 'extractplanes=y+u+v[y][u][v]' -map '[y]' y.yuv -map '[u]' u.yuv -map '[v]' v.yuv   
#其中[]表示别名,map可以引用别名

播放出现问题:

ffplay -s 864*486 y.yuv

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础

需要指定格式pix_fmt为单色,而不是按默认YUV去读取

ffplay y.yuv -pix_fmt gray -s 864*486

FFmpeg学习(四)视频基础

FFmpeg学习(四)视频基础 

注意:对于U、V分量,由于是YUV4:2:0,其中U、V分量只占1/2(即X,Y轴分辨率各自减少一半)

ffplay u.yuv -pix_fmt gray -s 432*243

FFmpeg学习(四)视频基础

(四)FFmpeg编程采集 

x11grab见:https://www.cnblogs.com/ssyfj/p/14576359.html

#include <stdio.h>
#include <libavutil/log.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>

void rec_video(){
    char* devicename = ":0.0";    //:前面为空,表示录制本地;:后面,如果NumA为0, 则表示连接到6000端口; 使用unix socket方式连接时则表示连接的unix socket的路径, 如果为0, 则表示连接到/tmp/.X11-unix/X0 . NumB则几乎总是0.
    char errors[1024];
    int ret,count=0,len;
    FILE* fp = NULL;

    AVFormatContext* fmt_ctx=NULL;    //格式上下文获取-----av_read_frame获取packet
    AVDictionary* options=NULL;
    AVInputFormat *iformat=NULL;
    AVPacket packet;    //包结构

    //获取输入(采集)格式
    iformat = av_find_input_format("x11grab");    //驱动,用来录制桌面
    //设置参数
    av_dict_set(&options,"video_size","1024*768",0);
    av_dict_set(&options,"framerate","15",0);

    //打开输入设备
    ret = avformat_open_input(&fmt_ctx,devicename,iformat,&options);    //----打开输入设备,初始化格式上下文和选项
    if(ret<0){
        av_strerror(ret,errors,1024);
        av_log(NULL,AV_LOG_ERROR,"Failed to open video device,[%d]%s\n",ret,errors);
    }
    
    av_log(NULL,AV_LOG_INFO,"Success to open video device\n");
    //打开文件
    fp = fopen("./video.yuv","wb");
    if(fp==NULL){
        av_log(NULL,AV_LOG_ERROR,"Failed to open out file\n");
        goto fail;
    }

    //开始从设备中读取数据
    while((ret=av_read_frame(fmt_ctx,&packet))==0&&count++<500){
        av_log(NULL,AV_LOG_INFO,"Packet size:%d(%p),cout:%d\n",packet.size,packet.data,count);

        fwrite(packet.data,1,packet.size,fp);
        fflush(fp);

        //释放空间
        av_packet_unref(&packet);
    }
fail:

    if(fp)
        fclose(fp);

    //关闭设备、释放上下文空间
    avformat_close_input(&fmt_ctx);
    return ;
}

int main(int argc,char* argv)
{

    av_register_all();
    av_log_set_level(AV_LOG_DEBUG);
    //注册所有的设备,包括我们需要的音频设备
    avdevice_register_all();

    rec_video();
    return 0;
}
View Code

相关文章:

  • 2022-12-23
  • 2021-05-28
  • 2021-12-24
  • 2022-12-23
  • 2021-06-27
  • 2021-11-13
  • 2021-09-11
  • 2022-12-23
猜你喜欢
  • 2021-05-01
  • 2021-12-22
  • 2022-02-01
  • 2022-01-10
  • 2022-01-25
  • 2021-08-20
相关资源
相似解决方案