控制视频播放速度(使用Sleep函数)
总体思路:在主函数中初始化SDL,读取文件,将数据交给线程Main,在线程Main中,通过while循环,以及用户设置的fps,根据fps的计算,读取数据进入View()函数中进行处理。
主函数
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061SDLQtRGB::SDLQtRGB(QWidget *parent) : QWidget(parent){ ui.setupUi(this); // 打开yuv文件 yuv_file.open("400_300_25.yuv", std::ios::binary); // 拿到文件大小 yuv_file.seekg(0, ios::end); // 移到文件结尾 file_size = yuv_file.tellg(); // 文件指针位置,获取文件大小 yuv_file.seekg(0, ios::beg); ...
ffmpeg学习记录
视频、图片格式介绍
使用 SDL 进行 RGB 渲染
使用 SDL 将两幅图片合并
SDL 播放 YUV 格式视频
XVideoView
XSDL
AVFrame 介绍
IO 文件操作
控制视频播放速度 (使用 Sleep 函数)
YUV、RGBA相互转换
ffmpeg 库进行编码
编码压缩(I、P、B帧,GOP)
XCodec
XEncode
AVCodec、AVCodecContext
ffmpeg库进行解码
XDecode
AVStream、AVFormatContext
AVCodecParameters
AVPacket
截取一段视频
XFormat
XMux
XDemux
编码encoder,解码decoder,复用mux,解复用demux关系
责任链设计模式
XTools
XDecodeTask
XMuxTask
XDemuxTask
AVFrame介绍
AVFrame介绍
AVFrame 是 FFmpeg 库中用于存储音视频数据帧的核心结构体。它在处理视频解码、编码、滤镜以及其他音视频处理任务时非常重要。AVFrame 可以表示原始的未压缩音频或视频数据。
AVFrame 的作用:
视频帧:在处理视频时,AVFrame 用于存储解码后的原始视频帧,每个帧包括像素数据、分辨率、格式、时间戳等信息。
音频帧:在处理音频时,AVFrame 用于存储解码后的原始音频数据,包括音频样本、通道布局、采样率等信息。
AVFrame 的结构:
AVFrame 是一个复杂的结构体,包含了大量与音视频数据相关的字段。以下是一些主要字段的介绍:
数据和缓冲区相关:
AV_NUM_DATA_POINTERS是 FFmpeg 库中的一个宏定义,它定义了用于指向数据平面的指针数组的大小。一般被定义为 8,这意味着数据指针数组 data[AV_NUM_DATA_POINTERS] 可以存储多达 8 个指向不同数据平面的指针。
uint8_t *data[AV_NUM_DATA_POINTERS]:指向存储数据的指针数组。对于视频,data[0] ...
视频、图片格式
YUV格式
YUV:"Y"表示明亮度(Luminance或Luma),也就是灰阶值,"U"和"V"表示的则是色度(Chrominance或Chroma)
为什么压缩数据一般采用YUV格式
与熟知RGB类似,YUV也是一种颜色编码方法,它是指将亮度参量(Y:Luminance或Luma)和色度参量(UV:Chrominance或Chroma)分开进行表示的像素编码格式
这样分开的好处就是不但可以避免相互干扰,没有UV信息一样可以显示完整的图像因而解决了彩色电视与黑白电视的兼容问题;还可以降低色度的采样率而不会对图像质量影响太大,降低了视屏信号传输时对频宽(带宽)的要求。
Y共用一组UV分量
YUV具体格式
YUV444
表示$4:4:4$的YUV取样。
每个像素都有独立的Y、U、V分量。
每一个像素Y占一个字节,U占一个字节,V占一个字节,因此每个像素占:
$$1 (Y)×8 bits+1 (U)×8 bits+1 (V)×8 bits=24 bits/pixel (bpp)$$
以$2\times 2$像素的图像为例
...
SDL播放YUV格式视频
代码
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879#include "sdlqtrgb.h"#include <sdl/SDL.h>#include <QMessageBox>#include <iostream>#include <fstream>#pragma comment(lib, "SDL2.lib")static int sdl_width = 0;static int sdl_height = 0;static SDL_Window* sdl_win = nullptr;static SDL_Renderer* sdl_render = nullptr;static SDL_Texture* sdl_texture = nullptr; ...
使用SDL将两幅图片合并
代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115#include "sdlqtrgb.h"#include <sdl/SDL.h>#include <QMessageBox>#include <iostream>#pragma comment(lib, "SDL2.lib")static int sdl_width = 0;static int sdl_height = 0;static SDL_Window* sdl_win = nullptr;static SDL_Renderer* ...
使用SDL进行RGB渲染
代码
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#include "sdlqtrgb.h"#include <sdl/SDL.h>#include <iostream>#pragma comment(lib, "SDL2.lib")static int sdl_width = 0;static int sdl_height = 0;static SDL_Window* sdl_win = nullptr;static SDL_Renderer* sdl_render = nullptr;static SDL_Texture* sdl_texture = nullptr;static unsigned char* rgb = ...
ffmpeg 搜索栏
项目地址。
XVideoView。
XVideoView是XSDL的基类。
XVideoView作用:
将传入的AVCodecParameters交给XSDL,用于处理sdl初始化
读取每一帧的数据
将传入的文件打开
根据传入的参数,返回XVideoView类,默认为XSDL
计算 fps,根据 format 进行绘制,Draw () 函数在基类 XSDL 中
XSDL。
XSDL继承于XVideoView。
XSDL作用:
初始化sdl
检查sdl窗口是否关闭
清理材质、渲染器、窗口句柄指针
处理YUV或RGB格式,渲染到sdl窗口上
XCodec。
XCodec是编解码的基类,也就是XEncode、XDecode的基类
XCodec作用:
根据传入的参数,新创建并返回解码器或编码器AVCodecContext(关于AVCodecContext介绍在这里)
设置类中的编解码器上下文AVCodecContext
设置类中编解码器上下文一些参数
打开编解码器
根据上下文AVCodecContext创建一个AVFrame
XEncode。
继承于XCodec
XEnco ...
XViewer Project
main.cpp
作为Qt的启动函数,通过创建XViewer对象。
然后调用show()函数在屏幕上进行显示。
接着调用exec()函数,启动Qt的循环事件,此时程序可以处理用户输入的一些请求。
12345678910int main(int argc, char *argv[]){ QApplication a(argc, argv); XViewer w; w.show(); auto re = a.exec(); // xr.Stop(); return re;}
xviewer
xviewer.h
用于第一个Qt创建的对象,可以通过自定义函数进行一些关于界面事件的处理。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#pragma once#include <QtWidgets/QWidget>#include "ui_xviewer. ...
XDemuxTask
XDemuxTask.h
123456789101112131415161718192021222324252627282930313233343536373839404142#pragma once#include "xtools.h"#include "xdemux.h"enum XSYN_TYPE{ XSYN_NONE = 0, // 不做同步 XSYN_VIDEO = 1, // 根据视频同步,不处理音频};class XDemuxTask : public XThread{public: void Main(); // 打开解封装 // url: rtsp地址 // timeout_ms:超时时间 单位毫秒 bool Open(std::string url, int timeout_ms = 1000); // 复制视频参数 std::shared_ptr<XPara> CopyVideoPara() { return demux_.CopyVideoPara(); ...