ffmpeg最简单的解码保存YUV数据

2023-11-20

文章转载自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&id=4584541&uid=24922718

video的raw data一般都是YUV420p的格式,简单的记录下这个格式的细节,如有不对希望大家能指出。

   YUV图像通常有两种格式,一种是packet 还有一种是 planar
    从字面上就能理解packet的意思就是所有的yuv数据都是一股脑的放在一起,当然 内部的数据还是按照格式要求的,只是从外部来讲是一整个包包含了所有的yuv数据。最长见的YUV格式就是planar格式了。这个格式是讲yuv三个分量分别放在三个数组里。
   如下图是个420p的格式图:

   
 

YUV420格式是指,每个像素都保留一个Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,则其接着一行就只取V分量,以此重复(即4:2:0, 4:0:2, 4:2:0, 4:0:2 …….),所以420不是指没有V,而是指一行采样只取U,另一行采样只取V。在取U和V时,每两个Y之间取一个U或V。但从4×4矩阵列来看,每4个矩阵点Y区域中,只有一个U和V,所以它们的比值是4:1。所以对于一个像素,RGB需要8 * 3 = 24位,即占3个字节;而YUV420P,8 + 8/4 + 8/4 = 12位,即占2个字节,其中8指Y分量,8/4指U和V分量。

所以从上可以知道,一般一个视频如果是yuv420p的raw data, 则他的每帧图像的大小计算公式:width*height*3/2

   ffmpeg中是如何管理这个yuv的数据的呢?
    核心就是AVFrame这个结构体,成员data是个指针数组,每个成员所指向的就是yuv三个分量的实体数据了,成员 linesize是指对应于每一行的大小,为什么需要这个变量,是因为在YUV格式和RGB格式时,每行的大小不一定等于图像的宽度。 所以很容易想象yuv的布局格式。如下图
   
事实上绝大多数的情况都是这样布局的,所以可以看出 数据时从左往右填充,但是不一定能填满。

        好了,知道了这些就很容易解码保存yuv数据了,废话不多说直接上代码

const char* SRC_FILE = "1.mp4";

int main()
{
    FILE *yuv_file = fopen("yuv_file","ab");
    if (!yuv_file)
        return 0;
    av_register_all();
    AVFormatContext* pFormat = NULL;
    if (avformat_open_input(&pFormat, SRC_FILE, NULL, NULL) < 0)
    {
        return 0;
    }
    AVCodecContext* video_dec_ctx = NULL;
    AVCodec* video_dec = NULL;
    if (avformat_find_stream_info(pFormat, NULL) < 0)
    {
        return 0;
    }
    av_dump_format(pFormat,0,SRC_FILE,0);
    video_dec_ctx = pFormat->streams[0]->codec;
    video_dec = avcodec_find_decoder(video_dec_ctx->codec_id);
    if (avcodec_open2(video_dec_ctx, video_dec, NULL) < 0)
    {
        return 0;
    }
    AVPacket *pkt = new AVPacket();
    av_init_packet(pkt);
    while (1)
    {
        if (av_read_frame(pFormat, pkt) < 0)
        {
            fclose(yuv_file);
            delete pkt;
            return 0;
        }
        if (pkt->stream_index == 0)
        {
            AVFrame *pFrame = avcodec_alloc_frame();
            int got_picture = 0,ret = 0;
            ret = avcodec_decode_video2(video_dec_ctx, pFrame, &got_picture, pkt);
            if (ret < 0)
            {
                delete pkt;
                return 0;
            }
            if (got_picture)
            {
                char* buf = new char[video_dec_ctx->height * video_dec_ctx->width * 3 / 2];
                memset(buf, 0, video_dec_ctx->height * video_dec_ctx->width * 3 / 2);
                int height = video_dec_ctx->height;
                int width = video_dec_ctx->width;
                printf("decode video ok\n");
                int a = 0, i;
                for (i = 0; i<height; i++)
                {
                    memcpy(buf + a, pFrame->data[0] + i * pFrame->linesize[0], width);
                    a += width;
                }
                for (i = 0; i<height / 2; i++)
                {
                    memcpy(buf + a, pFrame->data[1] + i * pFrame->linesize[1], width / 2);
                    a += width / 2;
                }
                for (i = 0; i<height / 2; i++)
                {
                    memcpy(buf + a, pFrame->data[2] + i * pFrame->linesize[2], width / 2);
                    a += width / 2;
                }
                fwrite(buf, 1, video_dec_ctx->height * video_dec_ctx->width * 3 / 2, yuv_file);
                delete buf;
                buf = NULL;
            }
            avcodec_free_frame(&pFrame);
            
            
        }
    }

    return 0;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ffmpeg最简单的解码保存YUV数据 的相关文章

随机推荐

  • Python 字符串包含

    Python String 类有 contains 我们可以使用它来检查它是否包含另一个字符串的函数 Python 字符串包含 Python字符串 contains 是一个实例方法 根据字符串对象是否包含指定的字符串对象 返回布尔值 Tru
  • 如何在 Ubuntu 14.04 上使用 Docker 和 Docker Compose 配置持续集成测试环境

    文章来自Docker 介绍 持续集成 CI 是指开发人员的实践整合尽可能频繁地编写代码 并且每次提交在合并到共享存储库之前和之后都会经过测试自动构建 CI speeds up your development process and min
  • Android BroadcastReceiver 示例教程

    今天我们将讨论并实现Android BroadcastReceiver 它是Android Framework中非常重要的组件 Android 广播接收器 Android BroadcastReceiver是android的一个休眠组件 用
  • 蟒蛇集

    In this tutorial we are going to learn Python Set In our previous article we learnt about Python String You can learn it
  • 如何在 Ubuntu 12.10 上使用 Python 创建 Nagios 插件

    介绍 Python 是 Linux 上默认提供的流行命令处理器 我们之前已经介绍过如何在Ubuntu 12 10 x64上安装Nagios监控服务器 这次 我们将扩展这个想法并使用 Python 创建 Nagios 插件 这些插件将在客户端
  • 如何编辑 Sudoers 文件

    介绍 权限分离是 Linux 和类 Unix 操作系统中实现的基本安全范例之一 普通用户以有限的权限进行操作 以减少对自己环境 而不是更广泛的操作系统 的影响范围 一个特殊的用户 称为root has 超级用户特权 这是一个管理帐户 没有普
  • JSTL 教程、JSTL 标签示例

    JSTL 代表JSP 标准标签库 JSTL 是标准标记库 它提供标记来控制 JSP 页面行为 JSTL 标签可用于迭代和控制语句 国际化 SQL 等 我们将在本 JSTL 教程中详细研究 JSTL 标签 之前我们看到了如何使用JSP EL
  • 了解 Python 3 中的类继承

    介绍 面向对象编程创建可重用的代码模式 以减少开发项目中的冗余 面向对象编程实现可回收代码的一种方法是通过继承 此时一个子类可以利用另一个基类的代码 本教程将介绍 Python 中继承的一些主要方面 包括父类和子类如何工作 如何重写方法和属
  • 电商java 面试题_JAVA电商项目面试题(一)

    需要按照功能点把系统拆分 拆分成独立的功能 单独为某一个节点添加服务器 需要系统之间配合才能完成整个业务逻辑 叫做分布式 集群 同一个工程部署到多台服务器上 优点 1 把模块拆分 使用接口通信 降低模块之间的耦合度 2 把项目拆分成若干个子
  • Rabbitmq消息的有序性、消息不丢失、不被重复消费

    如何保证消息的顺序性 如图所示 RabbitMQ保证消息的顺序性 就是拆分多个 queue 每个 queue 对应一个 consumer 消费者 就是多一些 queue 而已 确实是麻烦点 或者就一个 queue 但是对应一个 consum
  • 查经 民数记3章 利未人

    3章 利未人 1 4节 亚伦的儿子们 5 13节 利未人的职责 14 39 利未人男丁的统计 40 51节 利未人代替长子的地位 本章记载了利未人被神呼召 代替以色列各家长子成为事奉神的人 利未人的宗族 人数 及各族负责的事务 这件事灵意上
  • 程序的调试技巧。

    什么是调试 调试又叫Debug 又称除错 是发现和减少计算机程序或电子仪器设备中程序错误的一个过程 生活中所有发生的事情都一定有迹可循 如果问心无愧 就不需要掩盖也就没有迹象了 如果问心有愧疚 必然需要掩盖 那就一定会有迹象 迹象越多就容易
  • 如何控制asp.net控件TextBox输入内容的长度--(多种方法)

    2009 10 22 17 36 件代码如下
  • 在 CentOS 上安装 Docker Engine

    文章目录 在 CentOS 上安装 Docker Engine 先决条件 操作系统要求 卸载旧版本 安装方法 使用 rpm 存储库安装 设置存储库 安装 Docker Engine 安装最新版本 安装指定版本 以非 root 用户身份管理
  • js获取时间戳的四种方法

  • vscode使用手册

    VS Code Visual Studio Code 是一款轻量级 跨平台的源代码编辑器 支持语法高亮 自动补全 调试 Git 版本控制等功能 下面是一些使用 VS Code 的基本操作 安装和启动 在官网上下载并安装 VS Code 打开
  • react里面的接口调用方法

    react接口调用 我们通过npm create react app my app创建react项目 在项目里都是要进行接口调用来获取数据 进行增删改查各种操作的 所以掌握接口调用方式是非常必要的 话不多说进入正题 想要掌握接口调用的内里逻
  • 何恺明组《Designing Network Design Spaces》的整体解读(一篇更比六篇强)

    本文原载自知乎 已获原作者授权转载 请勿二次转载 https zhuanlan zhihu com p 122557226 statistics 大法好 DL不是statistics 因为DL不如statistics 基本全文从统计学的角度
  • 编程猫python讲师面试_【编程猫教师面试】笔试:试题+打字测速-看准网

    985师范本加硕 想要从事k12教育 坚挺到最后一轮但是未通过的小姐姐掩面飘过 来谈谈我的面试感受吧 个人觉得猫厂管培生的面试整体流程安排挺合理的 有感觉确实是在用心的挑选人才 然后所有的面试官都很nice 我是直接在boss直聘上投的简历
  • ffmpeg最简单的解码保存YUV数据

    文章转载自 http blog chinaunix net xmlrpc php r blog article id 4584541 uid 24922718 video的raw data一般都是YUV420p的格式 简单的记录下这个格式的