本篇文章用编程来介绍一下视频的一些基本元素
视频码率(kb/s):
视频码率,也称作比特率,是指视频文件在单位时间内传输的数据量,也就是视频流传输的质量,一般用kbps(千位每秒)为单位。码率越高,视频的质量就越好,但是文件体积也会相应增大。在同等分辨率的情况下,视频码率低 画面就可能有点模糊 视频码率高 视频就会清晰很多
视频码率可以理解为取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件。然而,文件体积与取样率是成正比的,因此,如何在保证视频质量的前提下尽可能减小文件体积,是视频编码技术的一个重要问题。围绕这个问题,衍生出了固定码率(CBR)和可变码率(VBR)等编码方式。
视频帧率 fps:
视频帧率(Frame rate)是用于测量显示帧数的量度,也就是每秒钟传输或显示的帧数,通常用FPS(Frames Per Second)表示。帧率越高,视频的画面就越流畅,细节表现也更好。视频帧率与视频分辨率、编码格式等因素密切相关。一般来说,在分辨率越高的情况下,为了保证画面的流畅性和清晰度,需要更高的帧率。同时,不同的编码格式对帧率的支持也不同,因此在选择编码格式时也需要考虑帧率的需求。
视频分辨率:
视频分辨率指视频图像的水平和垂直方向的像素数量,通常以“水平像素数×垂直像素数”的形式表示,如1920×1080。它是衡量视频质量的一个重要指标,分辨率越高,视频画面包含的像素点越多,显示出的图像就越清晰。
视频分辨率与图像传感器、显示设备和视频编码格式等因素有关。一般来说,图像传感器的像素数量越高,能够捕捉到的细节就越多,视频分辨率也就越高。同时,高分辨率的视频也需要更高性能的显示设备才能完全展现其效果。
I帧:独立解码 具体应用 当我们在桌面上存一个图片的时候 能够在软件里面独立的显示出来 这样的称为I帧
P帧 不能够独立解码 需要参考前面最靠近他的I帧或者P帧
B帧 需要同时参考前后帧
下图解释了GOF(大量帧的集合)使用的编解码过程
下面对这个图进行分析:
I帧解出P帧 (第一个P显示的是第二个编解码)第四个显示 依次类推
DTS:DTS(Digital Theater System)是数字影院系统的意思,它是一种用于电影院和其他大型数字音频系统的音频编码技术。DTS的核心是采用高码率的音频编码方案,让观众在欣赏电影时能够体验到接近无损的音质效果。
PTS:PTS是Percentage Points的缩写,常用于描述百分比的变化或增减。它不同于百分比(percentage)的概念,百分点表示一个绝对的变化量,而百分比表示一个相对的比例。
I帧 B帧 P帧代码实例:
1.初始化ffmpg库
2.编码实现
sudo apt-get install libavcodec-dev libavformat-dev 然后,你可以使用以下代码示例来编码视频帧:
#include <iostream> #include <x264.h> #include <x264_encoder.h> extern "C" { #include <libavcodec/avcodec.h> #include <libav 25; // 帧率分子 param.i_fps_den = 1; // 帧率分母 param.iformat/avformat.h> #include <libswscale/swscale.h> } int main(int argc, char* argv[])_timebase_num = 1; // 时间基准分子 param.i_timebase_den = 1; // 时间基准分母 param.i_threads = 0; // 使用默认数量的线程 param.i_level_idc = 0; { av_register_all(); // 打开输入视频文件 AVFormatContext* pFormatCtx = avformat_alloc_context(); // 等级(留空为自动选择) param.b_interlaced = 0; // 非交错视频 param.b_constrained_intra = 0; // 无约束的帧内预测 param.i_scenecut_threshold = 40; // if (avformat_open_input(&pFormatCtx, "input_video.mp4", NULL, NULL) != 0) 场景切换阈值 param.b_trellis = 1; // 使用trellis量化 param.i_quant_factor { printf("Couldn't open file\n"); return -1; } // 获取流信息 if (avformat_ = 25; // 量化因子 param.b_cabac = 1; // 使用CABAC熵编码 param.i_bframe = 3; // 使用3个B帧 param.i_bframe_adaptive = 1; // 自适应B帧决策 param.i_bframe_bias = 0; // B帧偏置 param.i_rc_find_stream_info(pFormatCtx, NULL) < 0) { printf("Couldn't find stream information\n"); method = X264_RC_CRF; // 使用CRF率控制 param.f_rf_constant = 23.0return -1; } // 查找视频流 int video_stream_index = -1; for (unsigned int i =; // CRF值 param.i_keyint_max = 250; // 最大关键帧间隔 param.i_keyint_min = 25; // 最小关键帧间隔 param.i_scenecut_bias = 25; // 场景切换偏置 // 分配编码器 x264_t *encoder = x264_encoder_open 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codecpar->(¶m); if (!encoder) { std::cerr << "Failed to open encoder!" << std::endl; return -1;codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if } // 编码循环(这里省略了读取帧的代码) // 假设你有一个函数来读取下一帧图像(get_next_frame) // image_t img; // while (get_next_frame(&img)) { // ... (video_stream_index == -1) { printf("Didn't find a video stream\n"); return -1; // } // 编码一帧图像 x264_picture_t pic; x264_picture_alloc(&pic, X264_CSP_I420, param.i_width, param.i_height); // 填充pic.img[0].plane[], pic.img[1].plane[], pic.img[2].plane[] // 这里应该} // 获取解码器上下文 AVCodecContext* pCodecCtx = avcodec_alloc_context3(NULL); AVCodec* pCodec加载你的原始图像数据到pic结构体中 int i_nal, i_size; uint8_t *p_nal; = avcodec_find_decoder(pFormatCtx->streams[video_stream_index]->codecpar->codec_id); if (x264_nal_t *nal = NULL; // 编码一帧 int ret = x264_encoder_encode(encoder, &nal, &i_nal, &pic, &i_size); if (ret < 0) {pCodec == NULL) { printf("Unsupported codec!\n"); return -1; } if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[video_stream_index]->codecpar) < 0) { printf("Could not set codec parameters.\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec\n"); return -1; } // 分配视频帧 AVFrame* pFrame = av_frame_alloc(); AVFrame* pFrameRGB = av_frame_alloc(); if (!pFrame || !pFrameRGB) { printf("Could not allocate video frame\n"); return -1; } // 设置像素格式转换上下文 struct SwsContext* img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); // 打开输出文件 AVFormatContext* outFormatCtx = avformat_alloc_context(); AVStream* outStream = avformat_new_stream(outFormatCtx, NULL); AVCodecContext* outCodecCtx = avcodec_alloc_context3(NULL); outCodecCtx->bit_rate = 400000; outCodecCtx->width = pCodecCtx->width; outCodecCtx->height = pCodecCtx->height; outCodecCtx->time_base = (AVRational){1, 25}; outCodecCtx->framerate
总结:我们要熟悉I帧 B帧 P帧的使用 视频码率 视频分辨率 视频频率的基础概念 视频码率和视频分辨率决定视频清晰程度 视频频率决定视频的流畅性
好了 本篇文章就到这里 下面我给大家推荐一个课程: