ffmpeg 视频解码一

2023-11-03

1. ffmpeg 视频解码一
2. ffmpeg 视频解码二
3. ffmpeg 音频解码一
4. ffmpeg 音频解码二
5. ffmpeg 音视频解码
6. ffmpeg 视频编码一
7. ffmpeg 视频编码一(精简版)
8. ffmpeg 视频编码二(基于 libswscale 转换视频)
9. ffmpeg 过滤器libavfilter的使用
10. ffmpeg 视频编码三(基于 libavfilter 转换视频)

前言

ffmpeg的大版本都已经更新到4了,近段时间我也研究了一下,从这篇文章开始,我将写一个系列,阐述一下ffmpeg API的使用。这篇文章为第一篇,就仅仅讲述一下视频解码相关的使用吧(视频解码会写两篇,这为第一篇,分别使用不同的API)。

流程图

在这里插入图片描述
代码流程即如流程图所示,下面讲解一下当中部分函数的作用。

  1. av_parser_init
    这是一个解析器,我们根据解码器,实例化这个解析器,后面解析数据时使用。
  2. av_parser_parse2
    我们从输入文件得到的原始数据(不适用ffmpeg自带的api的话),直接使用是不行的,此时我们就需要把这个原始数据使用上面实例化的解析器来解析,把数据分割成帧,为后面解码数据做准备。
  3. avcodec_send_packet
    发送我们刚刚得到的解析数据到解码器做解码。
  4. avcodec_receive_frame
    获取解码之后的数据。

源码


#pragma once
#define __STDC_CONSTANT_MACROS
#define _CRT_SECURE_NO_WARNINGS

extern "C"
{
#include "libavcodec/avcodec.h"
}

#define INBUF_SIZE 4096

using namespace std;

#define INPUT_FILE_NAME "lh_online.h264"
#define OUTPUT_FILE_NAME "lh_online.yuv"


static void decode(AVCodecContext* dec_ctx, AVFrame* frame, AVPacket* pkt,
	FILE* ofile)
{
	int ret;
	int y_size;
	ret = avcodec_send_packet(dec_ctx, pkt);
	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR, "发送数据包到解码器出错。\n");
		exit(1);
	}

	while (ret >= 0) {
		ret = avcodec_receive_frame(dec_ctx, frame);
		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
			return;
		else if (ret < 0) {
			av_log(NULL, AV_LOG_ERROR, "Error sending a packet for decoding.\n");
			exit(1);
		}
		//此时一帧视频已经保存到frame中了
		// 
		//打印输出的视频帧的帧数
		av_log(NULL, AV_LOG_INFO, "saving frame:%d , width: %d ,height: %d.\n", dec_ctx->frame_number, frame->width, frame->height);
		//获取一帧视频数据大小
		y_size = frame->width * frame->height;
		fwrite(frame->data[0], 1, y_size, ofile);    //Y
		fwrite(frame->data[1], 1, y_size / 4, ofile);  //U
		fwrite(frame->data[2], 1, y_size / 4, ofile);  //V
	}
}

int main(int argc, char* argv[])
{
	const AVCodec* codec;
	AVCodecParserContext* parser;
	AVCodecContext* c = NULL;
	FILE* ifile, * ofile;
	AVFrame* frame;
	AVPacket* pkt;
	uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
	uint8_t* data;
	size_t   data_size;
	int ret;

	//初始化inbuf数组
	memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);

	//获取解码器(此处需要读取的文件是H264,故)
	codec = avcodec_find_decoder(AV_CODEC_ID_H264);
	if (!codec) {
		av_log(NULL, AV_LOG_ERROR, "Codec not found.\n");
		exit(1);
	}

	//注册解析器
	parser = av_parser_init(codec->id);
	if (!parser) {
		av_log(NULL, AV_LOG_ERROR, "parser not found.\n");
		exit(1);
	}

	//分配解析器上下文
	c = avcodec_alloc_context3(codec);
	if (!c) {
		av_log(NULL, AV_LOG_ERROR, "Could not allocate video codec context.\n");
		exit(1);
	}

	//打开解码器
	if (avcodec_open2(c, codec, NULL) < 0) {
		av_log(NULL, AV_LOG_ERROR, "Could not open codec.\n");
		exit(1);
	}

	//分配AVPacket
	pkt = av_packet_alloc();
	if (!pkt) {
		exit(1);
	}

	//分配AVFrame
	frame = av_frame_alloc();
	if (!frame) {
		exit(1);
	}

	//打开输入文件
	ifile = fopen(INPUT_FILE_NAME, "rb");
	if (!ifile) {
		av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", INPUT_FILE_NAME);
		exit(1);
	}
	//打开输入文件
	ofile = fopen(OUTPUT_FILE_NAME, "wb+");
	if (!ofile) {
		av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", OUTPUT_FILE_NAME);
		exit(1);
	}


	while (!feof(ifile)) {
		//从输入流 ifile 读取数据到 inbuf 所指向的数组中
		data_size = fread(inbuf, 1, INBUF_SIZE, ifile);
		if (!data_size)
			break;

		//使用注册的解析器 parser 把数据分割成帧
		data = inbuf;
		while (data_size > 0) {
			ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,
				data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
			if (ret < 0) {
				av_log(NULL, AV_LOG_ERROR, "Error while parsing.\n");
				exit(1);
			}
			//根据使用情况重置数据位置
			data += ret;
			data_size -= ret;

			if (pkt->size) {
				decode(c, frame, pkt, ofile);
			}
		}
	}

	//flush 解码器
	decode(c, frame, NULL, ofile);

	//资源释放
	fclose(ifile);
	fclose(ofile);

	av_parser_close(parser);
	avcodec_free_context(&c);
	av_frame_free(&frame);
	av_packet_free(&pkt);

	return 0;
}

这个示例中我们把一个H264编码的 lh_online.h264 的文件解码成原始YUV视频文件 lh_online.yuv(这里不做YUV的介绍)。
下面我们使用ffplay来播放我们刚刚解码出来的视频原始数据(播放路径以自己实际路劲为准)。

ffplay -i C:\...\lh_online.yuv -pix_fmt yuv420p -s 512*288

注意两点:

  1. 此时我们播放的数据格式是 yuv 的(此处可设置可不设置,ffplay默认可播放)。
  2. 我们需要知道视频的原始宽高,代码里有个位置获取了宽高的(dec_ctx->frame_number, frame->width, frame->height),我们需要把快其设置到命令里,否者是不能播放的(我这个文件是512*288的)。

下面看下效果。
在这里插入图片描述

到此,基于parser解析器的解码就完成了,我们任何知道文件格式的视频,如果直接基于文件读取的方式都可以使用这种方式。
下一篇将讲述纯基于API的方式,应该是比这个方便很多。

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

ffmpeg 视频解码一 的相关文章

  • 1 FFmpeg从入门到精通-FFmpeg简介

    1 FFmpeg从入门到精通 FFmpeg简介 2 FFmpeg从入门到精通 FFmpeg工具使用基础 3 FFmpeg从入门到精通 FFmpeg转封装 4 FFmpeg从入门到精通 FFmpeg转码 5 FFmpeg从入门到精通 FFmp
  • FFmpeg中的常见结构体

    代码基于FFmpeg5 0 1 目录 FFFormatContext AVFormatContext AVIOContext FFIOContext URLContext URLProtocol AVInputFormat FFStream
  • UE4的视频播放(Media Player)

    1 视频播放Begining 首先将需要播放的视频拖入 创建Media Player和Media Texture 创建Material 将材质改为User Interface 在UI界面 创建Image 将这个材质装入 在人物Pawn界面添
  • 视频稳像(Video Stabilization)

    原文 https blog csdn net hjl240 article details 52683738 开源 关键词 Video Stabilization 不错 https github com yaochih awesome vi
  • Android:播放UDP流例如udp://@239.0.0.3:8218

    成功实现播放udp github下载 求大佬们给个star GitHub YangWenlong71 udpplayer 基于ijk重新编译 未做删减几乎全能的安卓视频播放器 支持播放UDP https http 等 分割线 研究思路及结果
  • 清空v4l2 usbcamera缓存

    做过usbcamera的同学们应该都知道 usbcamera有一个缓存队列 当应用上面调用startPreview的时候 就会层层的调到usbcamera 的ioctl mFd VIDIOC DQBUF tmp buf 用于从队列里出去一个
  • 音视频学习笔记(雷神)—技术解析

    音视频技术解析 封装技术 视频压缩编解码 音频压缩编解码 这是技术层 流媒体传输协议 这是网络层 视频播放器解析 解协议 从视频播放器的角度做解析 拿到传输而来的视频数据后 首先要解协议 传输协议 自然的本地视频经过硬盘传输数据自然没有解协
  • public static void main(String[] args) { //填入通过分享获取到的抖音视频地址 String videoUrl = getVid...

    这段代码的作用是从抖音 douyin 分享链接中获取视频的无水印播放地址 首先 它通过调用 HttpRequest get url 方法获取抖音视频的分享页面的 HTML 源代码 然后 通过调用 sub 方法并传入 HTML 源代码 开始字
  • OpenCV实战(29)——视频对象追踪

    OpenCV实战 29 视频对象追踪 0 前言 1 追踪视频中的对象 2 中值流追踪器算法原理 3 完整代码 小结 系列链接 0 前言 我们已经学习了如何跟踪图像序列中点和像素的运动 但在多数应用中 通常要求追踪视频中的特定移动对象 首先确
  • 音视频开发开发核心知识+新手入门必看基础知识

    音视频开发是一个广泛的领域 它涉及到多个技术领域 包括音频编解码 视频编解码 媒体容器格式 流媒体传输 音视频处理等 以下是音视频开发的一些基础知识 音频编解码器 音频编解码器是将数字音频信号编码成一种压缩格式 并且能够解码压缩的音频数据以
  • 【ffmpeg基础】ffmpeg音频编码

    一 aac编码 输入raw音频编码为AAC ffmpeg i input wav acodec aac y input aac 通过 acodec来指定音频编码器 视频编码器为 vcodec 也可以使用 c a来指定音频编码器 ffmpeg
  • 海思编码:1、mpp系统详谈以及VI、VPSS、VENC之间的关系

    在HiMPP手册中都会有这么一张图 先讲一下视频缓存池这个概念 视频缓存池主要向媒体业务提供大块物理内存管理功能 负责内存的分配和回收 这部分具体什么作用 首先视频输入回需要大量的内存 打比方1080P的视频输入 VI部分怎么保存或者使用呢
  • 使用OpenCV与深度学习从视频和图像中精准识别人脸: Python实践指南

    第一部分 引言与背景 人脸识别已经成为了当代技术领域中最热门和广泛应用的话题之一 从智能手机的解锁功能到机场的安全检查 人脸识别技术无处不在 在这篇文章中 我们将使用Python中的OpenCV库和深度学习模型 深入探讨如何从视频和图像中精
  • 视音频数据处理入门:AAC音频码流解析

    vs调试内存 FF F9满足代码中的if判断条件 上图代码的目的是获取adts帧的长度 如上述评论 aac frame length占用13个bit 覆盖了buffer 3 buffer 4 buffer 5 下图为查找资料所得 用ue查看
  • 软件测试/人工智能丨计算机视觉场景中,如何处理视频/图片数据并进行测试

    在计算机视觉中 处理视频和图片数据并进行测试是一个关键的任务 以下是一些常见的步骤和方法 处理图片数据 数据加载 使用图像处理库 例如OpenCV PIL 加载图像数据 将图像转换为模型所需的格式 通常是矩阵 预处理 标准化图像 将图像像素
  • onvif协议笔记

    一 简介 ONVIF官网 ONVIF协议网络摄像机 IPC 客户端程序开发 1 专栏开篇 onvif协议开发 二 gSOAP gsoap官网 1 下载和编译 下载地址 bin sh 指定源码目录 解压源码 GSOAP SRC gsoap 2
  • 免费音效素材网站,一次性介绍清楚

    不管是在游戏 电影 电视剧 短视频还是音频中 合适的音效能够更好的表达内容和渲染氛围 今天给大家分享几个免费音效素材 感兴趣的话可以接着往下看 一 制片帮素材 找音效 制片帮素材不仅有海量的优质视频素材 还有丰富的音效资源 分类清晰 更重要
  • macbook录屏快捷键大全,教你快速录制视频

    有人知道macbook电脑有录屏快捷键吗 现在录屏的速度太慢了 每次打开都要浪费不少时间 要是有录屏快捷键 应该会快很多 有哪位大佬知道吗 教教我 无论是在工作还是生活中 电脑已成为不可或缺的工具 而macbook作为苹果公司推出的一款笔记
  • 光端机技术综述:从理论到实践的全面探索

    在当今数据驱动的时代 光端机技术 已成为通信领域的核心组成部分 从理论的深度研究到实践的广泛应用 光端机技术不断推动着信息社会的发展 成为连接不同设备和网络的关键技术 技术特点 高速数据传输 光端机 利用光纤传输数据 具有极高的传输速率 相
  • Waves14 Complete Mac/win功能强大、效果出色的专业级插件集合

    在现代音频制作中 音频效果器扮演着至关重要的角色 它们能够为音频注入独特的魅力和个性 让作品更加出彩 而在众多音频效果器中 Waves14 Complete音频效果器套件无疑是一个不可或缺的利器 Waves14 Complete音频效果器套

随机推荐

  • vant-list + toast分页加载,数据加载后会滚动至顶部

    vant list toast分页加载 数据加载后会滚动至顶部 主要原因是 toast组件在全局添加了 pointer event none 解决办法 在对应的van list的属性值添加 pointer event volunteer l
  • QT控件之(TableView)的居中效果

    T将tableView中的表头以及文本内容都进行居中处理 1 需要在构造函数中增加一句 以下增加的是表头的效果 ui gt tableView gt horizontalHeader gt setSectionResizeMode QHea
  • SQL注入之布尔盲注

    布尔盲注 如果确定页面注入点存在 如果页面没有回显并且没有报错信息可以考虑使用布尔盲注 布尔盲注的判断条件是页面布尔类型状态 当传递参数 id 1 and 1 1 这里以sqlilab的闯关为例 当传递参数 id 1 and 1 2 比较两
  • MyBatis学习(三):解析MyBatis的SQL映射XML文件写法和使用原理

    上面的两篇文章 分别是MyBatis的入门小程序和MyBatis的配置XML解析 有需要的可以先去看看这两篇文章 本篇文章 会来讲解SQL映射XML文件的写法以及如何使用 MyBatis真正的力量在于其映射语句 这里应该是奇迹发生的地方 S
  • Vue传参出现 Required String parameter 'username' is not present

    场景描述 在 使用axios 发送HTTP请求时 传递了后端指定的请求参数 但是后端报错 描述信息为 Required String parameter username is not present 分析问题 开始找原因 确定前端传递的参
  • jsp页面整合ECharts绘制图表(以折线图为例)

    文章目录 jsp页面整合ECharts绘制折线图 先看效果图 前端代码 后端测试代码 jsp页面整合ECharts绘制折线图 官网 https echarts apache org zh index html 官网上有demo可以直接调试样
  • 2021-06-15 好用的STF-Git项目

    好用的STF Git项目 1 基于openstf二次开发的群控管理平台 快速开始 Mac Linux centos 相关工具 测试使用版本 2 deploy stf docker 在Ubuntu上使用一键操作部署STF主服务器的脚本 1 基
  • Pyecharts——Python高级可视化

    Pyecharts是百度开源的移植到Python上的可视化工具 里面方法调用起来像是标记性语言 因此代码的可读性很强 一目了然 下面是一个绘制散点图的例子 import pyecharts options as opts from pyec
  • 出现 DeprecationWarning: BICUBIC is deprecated and will be removed in Pillow 10 的解决方法

    目录 1 问题所示 2 原理分析 3 解决方法 1 问题所示 使用plt代码模块的时候 问题如下 home kkjz anaconda3 envs py17 lib python3 7 site packages ipykernel lau
  • 强推,黑白照片一步完美上色,Picture Colorizer Pro Mac版

    今天在国外一个网站偶尔发现一个超棒的软件Picture Colorizer Pro专业版 黑白照片或老旧照片自动上色 心动不如行动 马上下载上手使用 效果超棒 它的强在在于色彩还原非常真实 有老照片的胶片感 边缘过度很精细 没有粗糙的感觉
  • 在C++中如何使用httpClient,用Newtonsoft解析JSON

    现在C 也不行了吗 网上找不到相关代码 为了搞清楚C 中如何使用httpClient和Newtonsoft 研究了一下午 我从未用C 编程 一直用C 现学现卖 https download csdn net download cnwjl 1
  • 深入浅出java并发编程(AbstractQueuedSynchronizer)(AQS)

    前言 Abstract抽象的 Ownable拥有 Synchronizer同步器 Queued队列 AbstractOwnableSynchronizer简称为AOS AbstractQueuedSynchronizer简称为AQS Abs
  • Springboot+mybatis+druid的整合

    最近的公司项目后端用到了Springboot框架 把阿里的druid作为数据源 采用mybatis druid的方式 本人之前也是在这里踩了很多坑 因此感觉有必要出个博客来记录一下 首先 用druid最为数据源的好处就不多说了 灵活动态切换
  • docker保存和加载tar及其tar.gz

    1 导出和加载tar 1 1 save和load命令 save命令 docker save options images images 示例 docker save o nginx tar nginx latest 或 docker sav
  • 005_关于QT之QWidget的事件处理机制

    一 eventFilter函数 事件过滤函数 一般用于容器组件来决定是否将事件传递给子组件 当前组件的事件过滤函数 在事件直接发生在当前组件时该组件的过滤函数是不被调用的 二 event函数 用于组件内部事件函数的分发 在这个函数内部调用事
  • opencv esp32cam的初步应用

    import urllib request import numpy as np import cv2 def cam esp32cam的ip地址 url 192 168 43 1 png 获取esp32cam的镜头 imgResp url
  • verilog case语句_verilog语法进阶

    欢迎FPGA工程师加入官方微信技术群 模块的结构 数据类型 变量和基本运算符号 3 1 模块的结构 Verilog的基本设计单元是 模块 block 一个模块是由两部分组成的 一部分描述接口 另一部分描述逻辑功能 即定义输入是如何影响输出的
  • 解决:Failed to execute goal org.apache.maven.pluginsmaven-archetype-plugin3.1.2generate

    问题 Failed to execute goal org apache maven plugins maven archetype plugin 3 1 2 generate default cli on project standalo
  • webpack server.js本机模拟数据

    文件路径 data json seller name 粥品香坊 回龙观 description 蜂鸟专送 deliveryTime 38 score 4 2 serviceScore 4 1 foodScore 4 3 rankRate 6
  • ffmpeg 视频解码一

    1 ffmpeg 视频解码一 2 ffmpeg 视频解码二 3 ffmpeg 音频解码一 4 ffmpeg 音频解码二 5 ffmpeg 音视频解码 6 ffmpeg 视频编码一 7 ffmpeg 视频编码一 精简版 8 ffmpeg 视频