x264编解码库 -介绍和使用示例

news2024/9/17 7:21:34

目录

1:X264简单介绍

       1.1:编译x264

     1.2:x264简单介绍

      1.3:x264的优势

     1.4:x264与FFmpeg的关系

        1.5:x264 编解码原理

    1.6 进一步学习资源

2:demo效果

3:完整代码

4:附件压缩包代码


1:X264简单介绍

       1.1:编译x264

         上一篇介绍了,如何基于Windows vs环境编译x264的步骤,https://blog.csdn.net/xiaoshuaijinniu/article/details/140712483icon-default.png?t=N7T8https://blog.csdn.net/xiaoshuaijinniu/article/details/140712483

     1.2:x264简单介绍

        x264是一个专门用于H264/MPEG-4 AVC视频编解码的开源库,始于2004年,目标就是为了 提供一个高效 稳定 高质量的H264编解码。在2012年左右大规模用于各个商业场景和开源框架中。

      1.3:x264的优势

        1:x264实现了H.264标准的所有高级特性,相同的图像质量下,实现了更高的压缩率,也就是数据更少了质量更高了,特别是低比特率下,提供更好的质量。

        2:支持多线程编码,可以利用多核处理器,提高编解码速率

        3:开源使用,而且应用平台很多,可以说是成为了行业标准,比如FFmpeg,VLC、YouTube、Twitch等等

     1.4:x264与FFmpeg的关系

        FFmpeg是一个开源的针对多媒体处理的开源库,音视频编解码、复用、流媒体、过滤、播放等功能,FFmpeg内部兼容支持了链接外部x264的使用,也就是在编译FFmpeg时,可以开启x264的模块使用,然后使用时,FFmpeg会遍历已注册的编解码器,找到x264编码器,FFmpeg内部也有自己的h264编解码器,之前性能不如x264,但现在发展的也足够一般情况下去使用了,所有可以根据自身的需求去选择。

通过集成 x264,FFmpeg 可以提供高效的 H.264 编码功能。FFmpeg 的灵活性和多功能性使其成为许多媒体处理任务的首选工具,而 x264 的高效编码能力则进一步增强了 FFmpeg 的性能。

      1.5:x264 编解码原理

x264 的编码过程主要包括以下几个步骤:

  1. 分块与分片:将输入图像分成多个宏块,每个宏块进一步划分为 4x4 或 8x8 的子块。
  2. 预测编码:使用帧内预测和帧间预测减少冗余数据。帧内预测通过相邻像素预测当前块,帧间预测通过参考之前或之后的帧预测当前块。
  3. 变换和量化:对预测残差进行离散余弦变换(DCT)和量化,减少不重要的高频系数。
  4. 熵编码:使用 CABAC 或 CAVLC(上下文自适应变长编码)对量化后的系数进行熵编码,提高压缩效率。
  5. 输出比特流:将编码后的数据打包成 NAL(网络抽象层)单元,形成最终的 H.264 比特流。

通过这些步骤,x264 能够实现高效的视频压缩,同时保持较高的图像质量。

    1.6 进一步学习资源

  • x264 官方文档
  • FFmpeg 官方文档
  • H.264 标准文档

2:demo效果

x264​​​​​​

3:完整代码

#include <iostream>
#include <string>
#include "stdint.h"
#pragma warning(disable : 4996) // 禁用4996号警告
#pragma comment(lib, "libx264.lib") // 链接x264库文件
extern "C"
{
#include "x264shared/include/x264.h"
#include "x264shared/include/x264_config.h"
}

// 读取 YUV 图像
int read_yuv_frame(FILE *fp, x264_picture_t *pic, int width, int height) {
    int y_size = width * height;  // 计算Y分量大小
    int uv_size = y_size / 4;     // 计算U和V分量大小,YUV 4:2:0格式下为Y的四分之一

    // 从文件中读取Y分量数据
    if (fread(pic->img.plane[0], 1, y_size, fp) != y_size) {
        return -1; // 如果读取失败,返回-1
    }
    // 从文件中读取U分量数据
    if (fread(pic->img.plane[1], 1, uv_size, fp) != uv_size) {
        return -1; // 如果读取失败,返回-1
    }
    // 从文件中读取V分量数据
    if (fread(pic->img.plane[2], 1, uv_size, fp) != uv_size) {
        return -1; // 如果读取失败,返回-1
    }

    return 0; // 成功读取返回0
}

int main(int argc, char** argv)
{
    printf("hello world.\n"); // 打印测试信息

    // 打开输入YUV文件
    FILE* in_file = fopen("E:\\hs\\hspro\\x264demo\\bin\\yuv_420-352x288.yuv", "rb");
    // 打开输出H.264文件
    FILE* out_file = fopen("E:\\hs\\hspro\\x264demo\\bin\\x.h264", "wb");
    
    if (!in_file) {
        fprintf(stderr, "Failed to open input file\n"); // 如果输入文件打开失败,打印错误信息
        return -1;
    }

    if (!out_file) {
        fprintf(stderr, "Failed to open output file\n"); // 如果输出文件打开失败,打印错误信息
        fclose(in_file); // 关闭已打开的输入文件
        return -1;
    }

    x264_t *encoder;              // x264编码器
    x264_picture_t pic_in, pic_out; // 输入和输出图像
    x264_param_t param;           // 编码参数
    x264_nal_t *nals;             // NAL单元
    int num_nals;                 // NAL单元数量

    // 初始化编码参数,使用“medium”预设和“zerolatency”选项
    x264_param_default_preset(&param, "medium", "zerolatency");
    param.i_bitdepth = 8;         // 位深度设置为8位
    param.i_csp = X264_CSP_I420;  // 色彩空间设置为I420
    param.i_width = 352;          // 视频宽度设置为352
    param.i_height = 288;         // 视频高度设置为288
    param.i_fps_num = 25;         // 帧率分子设置为25
    param.i_fps_den = 1;          // 帧率分母设置为1

    // 应用高质量的编码配置文件
    x264_param_apply_profile(&param, "high");

    // 打开x264编码器,使用设置好的参数
    encoder = x264_encoder_open(&param);
    if (!encoder) {
        fprintf(stderr, "Failed to open encoder\n"); // 如果编码器打开失败,打印错误信息
        fclose(in_file); // 关闭已打开的输入文件
        fclose(out_file); // 关闭已打开的输出文件
        return -1;
    }

    // 分配输入图像内存
    x264_picture_alloc(&pic_in, param.i_csp, param.i_width, param.i_height);
    // 初始化输出图像
    x264_picture_init(&pic_out);

    int frame_count = 0; // 初始化帧计数器
    // 从文件中读取一帧YUV图像并进行编码
    while (read_yuv_frame(in_file, &pic_in, param.i_width, param.i_height) == 0) {
        pic_in.i_pts = frame_count++; // 设置图像的时间戳(PTS)

        // 使用x264编码器编码图像,生成NAL单元
        int frame_size = x264_encoder_encode(encoder, &nals, &num_nals, &pic_in, &pic_out);
        if (frame_size < 0) {
            fprintf(stderr, "Failed to encode frame\n"); // 如果编码失败,打印错误信息
            x264_picture_clean(&pic_in); // 清理输入图像内存
            x264_encoder_close(encoder); // 关闭编码器
            fclose(in_file); // 关闭输入文件
            fclose(out_file); // 关闭输出文件
            return -1;
        }

        // 写入编码后的NAL单元到输出文件
        for (int i = 0; i < num_nals; i++) {
            fwrite(nals[i].p_payload, 1, nals[i].i_payload, out_file);
        }
    }

    // 清理输入图像内存
    x264_picture_clean(&pic_in);
    // 关闭编码器
    x264_encoder_close(encoder);
    // 关闭输入文件
    fclose(in_file);
    // 关闭输出文件
    fclose(out_file);

    return 0; // 程序成功结束
}

4:附件压缩包代码

之前有些对这些可能不是太熟悉的朋友说,代码有了,但是环境配置起来有些不一致或者其他情况,不知道怎么处理,我附上完整的代码包,后面的文章,我也尽量把完整的代码包作为附件去发。给需要的各位参考

http://链接:https://pan.baidu.com/s/1y5PJeNVfEQ_dvM2sjCKJ6Q?pwd=elpf 提取码:elpficon-default.png?t=N7T8http://链接:https://pan.baidu.com/s/1y5PJeNVfEQ_dvM2sjCKJ6Q?pwd=elpf 提取码:elpf

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

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

相关文章

Vite + Vue3 + TS项目配置前置路由守卫

在现代前端开发中&#xff0c;使用 Vue 3 和 TypeScript 的组合是一种流行且高效的开发方式。Vite 是一个极速的构建工具&#xff0c;可以显著提升开发体验。本文博主将指导你如何在 Vite Vue 3 TypeScript 项目中配置前置路由守卫&#xff08;Navigation Guards&#xff09;…

学习日记:数组

1. 概念 一组相同类型的数据的集合&#xff0c;也是一种数据类型。 2. 一维数组 2.1 语法 类型说明符 数组名 [常量表达式] &#xff08;1&#xff09; &#xff08;2&#xff09; &#xff08;3&#xff09; &#xff08;1&#xff09;类型说明符&#x…

Leetcode - 周赛407

目录 一&#xff0c;3226. 使两个整数相等的位更改次数 二&#xff0c;3227. 字符串元音游戏 三&#xff0c;3228. 将 1 移动到末尾的最大操作次数 四&#xff0c;3229. 使数组等于目标数组所需的最少操作次数 一&#xff0c;3226. 使两个整数相等的位更改次数 本题可以暴力…

刷题了:144.二叉树的前序遍历心|145.二叉树的后序遍历心|94.二叉树的中序遍历己

递归遍历 文章讲解:https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.html#%E6%80%9D%E8%B7%AF 视频讲解:https://www.bilibili.com/video/BV1Wh411S7xt/?spm_id_from333.788&vd_sourcee70917aa6392827d1ccc8d85e1…

ubuntu20.04安装nginx,mysql8,php7.4详细教程,包成功

目录 1.更新索引 2.安装 Nginx 1.安装 Nginx&#xff1a; 2.启动 Nginx 服务并设置为开机自启&#xff1a; 3.开放防火墙的 80 端口&#xff1a; 4.检查 Nginx 是否正常运行&#xff1a; 3.安装 MySQL 8.0 1.首先&#xff0c;安装 MySQL 的仓库&#xff1a; 安装过程中你会看…

Python --Pandas库基础方法(2)

文章目录 Pandas 变量类型的转换查看各列数据类型改变数据类型 重置索引删除行索引和切片seriesDataFrame取列按行列索引选择loc与iloc获取 isin()选择query()的使用排序用索引排序使用变量值排序 修改替换变量值对应数值的替换 数据分组基于拆分进行筛选 分组汇总引用自定义函…

TinyVue 组件库官网焕然一新!

本文由体验技术团队Kagol原创~ 之前有一些朋友吐槽我们 TinyVue 组件库的 UI 不够美观&#xff0c;于是我们请了设计师小姐姐给我们的组件和网站进行优化&#xff0c;经过设计师小姐姐和我们的开发兄弟们一个多月的努力&#xff0c;终于完成网站第一版的优化。 优化点 主要优…

学习react-登录状态验证

1.创建三个页面LoginPage, HomePage,NotFoundPage用于Router 创建LoginPage.tsx用于做登录页面 // LoginPage.tsx const LoginPage (props:LoginProp) > {const navigate useNavigate();return( <h1 onClick{ ()>{navigate("/");}}>Hello Login, {pr…

如何在Selenium Webdriver中点击SVG元素?

我们将在URL上单击下面突出显示的SVG元素&#xff1a;https&#xff1a;//testkru.com/Elements/SVGelemnts。 有几种方法可以点击SVG元素&#xff0c;我们将在这篇文章中讨论它们&#xff0c;并讨论它们之间应该首选哪一种。 使用 WebElement Click() 通过使用Action Click() …

前端JS特效第53集:带声音的烟花模拟绽放特效插件

带声音的烟花模拟绽放特效插件&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>Firework Simulator v2&…

五、SpringIoC/DI的使用

1. 类注解、方法注解 告诉spring管理bean—>bean的存储 1、类注解&#xff1a;五大注解 Controller&#xff08;控制器存储&#xff09;、 Service&#xff08;服务存储&#xff09;、 Repository&#xff08;仓库存储&#xff09;、 Component&#xff08;组件存储&#xf…

一种多策略改进黑翅鸢智能优化算法IBKA(2024年新出优化算法)种群初始化精英反向+透镜成像反向学习+黄金正弦变异策略

一种多策略改进黑翅鸢智能优化算法IBKA&#xff08;2024年新出优化算法&#xff09; 种群初始化精英反向策略透镜成像反向学习策略黄金正弦变异策略 文章目录 前言一种多策略改进黑翅鸢智能优化算法IBKA&#xff08;2024年新出优化算法&#xff09; 种群初始化精英反向策略透镜…

35_YOLOX网络详解

1.1 简介 YOLOX是YOLO系列&#xff08;You Only Look Once&#xff09;目标检测模型的一个最新变种&#xff0c;由阿里云团队和旷视科技在2021年提出。YOLO系列以其快速、准确的目标检测能力而闻名&#xff0c;而YOLOX在此基础上进行了多方面的改进和优化&#xff0c;旨在提供…

获取手机当前信号强度(dbm/asu值)解决 getGsmSignalStrength()总是返回99问题

能看到这篇文章说明网上哪些获取 &#xff08;dbm/asu值&#xff09;不适合你&#xff0c;不是他们的代码不正确&#xff0c;而是不符合你的情况 比如安卓6获取android手机信号强度 可以看这篇文章 https://blog.csdn.net/sinat_31057219/article/details/81134030 当然如果你…

计算机三级嵌入式(三)——嵌入式系统硬件组成

目录 考点1 嵌入式最小硬件系统 考点2 基于 ARM 内核的典型嵌入式应用系统硬件组成 考点3 ARM 的 AMBA 总线体系结构及标准 考点4 基于 ARM 内核的嵌入式芯片的硬件组成 考点5 存储器层次结构 考点6 存储器分类 考点7 存储器主要性能指标 考点8 片内存储器 考点9 外部…

Perfectly Clear WorkBench中文绿色版,让每一张照片都完美无瑕

软件简介 你是否曾经为了一张不完美的照片而感到遗憾&#xff1f;是否曾经因为照片中的小瑕疵而不得不花费大量时间进行后期处理&#xff1f;现在&#xff0c;有了Perfectly Clear WorkBench&#xff0c;这些问题都将迎刃而解。作为全球领先的智能图像校正技术商推出的图像清晰…

【C++高阶数据结构】红黑树:全面剖析与深度学习

目录 &#x1f680; 前言&#xff1a;红黑树与AVL树的比较一&#xff1a; &#x1f525; 红黑树的概念二&#xff1a; &#x1f525; 红黑树的性质 三&#xff1a; &#x1f525; 红黑树节点的定义和结构&#x1f680; 3.1 基本元素&#x1f680; 3.2 节点颜色&#x1f680; 3.…

Java中static静态变量--继承等相关知识

目录 static 继承&#xff1a; 继承的特点&#xff1a; 案例&#xff1a;自己设计一个继承体系练习&#xff1a; 设计思想&#xff1a; 代码&#xff1a; 子类到底能继承父类的哪些类容&#xff1f; 成员变量内存的继承情况&#xff1a; 成员方法的内存继承情况&#x…

项目经理的开源工具指南:优化您的选择过程

国内外主流的10款开源项目管理系统对比&#xff1a;PingCode、Worktile、禅道、Teambition、Gogs、码云 Gitee、Jira、Redmine、ProjectLibre、OpenProject。 在选择合适的开源项目管理系统时&#xff0c;很多团队面临诸多挑战&#xff1a;功能是否全面&#xff1f;易用性如何&…

C++初学(7)

7.1、字符串 字符串是存储在内存的连续字节中的一系列字符。C处理字符串的方式有两种&#xff0c;第一种是来自C语言&#xff0c;常被称为C风格字符串&#xff0c;另一种则是基于string类库的方法。 存储在连续字节中的一系列字符意味着可以将字符存储在char数组中&#xff0…