音视频实战---音视频解码
该方法只能解码裸流。
1、使用avcodec_find_decoder查找解码器
根据使用解码器类型,决定是解码音频还是解码视频。
2、 使用av_parser_init获取裸流解析器和方法
3、使用avcodec_alloc_context3分配编解码器上下文
4、使用avcodec_open2将解码器和解码器上下文进行关联
5、使用fopen打开输入、输出文件
6、使用fread读取文件
7、使用av_frame_alloc分配存储解码数据结构体,以接收解码数据
8、使用av_parser_parse2解析数据包获取到编码后的音视频帧,将获取到的音视频帧使用avcodec_send_packet发送到解码器上下文,使用avcodec_receive_frame接收解码后的数据,将解码后的数据根据相应格式写入文件中
/**
* @projectName 07-05-decode_audio
* @brief 解码音频,主要的测试格式aac和mp3
* @author Liao Qingfu
* @date 2020-01-16
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavutil/frame.h>
#include <libavutil/mem.h>#include <libavcodec/avcodec.h>#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096static char err_buf[128] = {0};
static char* av_get_err(int errnum)
{av_strerror(errnum, err_buf, 128);return err_buf;
}static void print_sample_format(const AVFrame *frame)
{printf("ar-samplerate: %uHz\n", frame->sample_rate);printf("ac-channel: %u\n", frame->channels);printf("f-format: %u\n", frame->format);// 格式需要注意,实际存储到本地文件时已经改成交错模式
}static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,FILE *outfile)
{int i, ch;int ret, data_size;/* send the packet with the compressed data to the decoder */ret = avcodec_send_packet(dec_ctx, pkt);if(ret == AVERROR(EAGAIN)){fprintf(stderr, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");}else if (ret < 0){fprintf(stderr, "Error submitting the packet to the decoder, err:%s, pkt_size:%d\n",av_get_err(ret), pkt->size);
// exit(1);return;}/* read all the output frames (infile general there may be any number of them */while (ret >= 0){// 对于frame, avcodec_receive_frame内部每次都先调用ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0){fprintf(stderr, "Error during decoding\n");exit(1);}data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);if (data_size < 0){/* This should not occur, checking just for paranoia */fprintf(stderr, "Failed to calculate data size\n");exit(1);}static int s_print_format = 0;if(s_print_format == 0){s_print_format = 1;print_sample_format(frame);}/**P表示Planar(平面),其数据格式排列方式为 :LLLLLLRRRRRRLLLLLLRRRRRRLLLLLLRRRRRRL...(每个LLLLLLRRRRRR为一个音频帧)而不带P的数据格式(即交错排列)排列方式为:LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL...(每个LR为一个音频样本)播放范例: ffplay -ar 48000 -ac 2 -f f32le believe.pcm*/for (i = 0; i < frame->nb_samples; i++){for (ch = 0; ch < dec_ctx->channels; ch++) // 交错的方式写入, 大部分float的格式输出fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile);}}
}
// 播放范例: ffplay -ar 48000 -ac 2 -f f32le believe.pcm
int main(int argc, char **argv)
{const char *outfilename;const char *filename;const AVCodec *codec;AVCodecContext *codec_ctx= NULL;AVCodecParserContext *parser = NULL;int len = 0;int ret = 0;FILE *infile = NULL;FILE *outfile = NULL;uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t *data = NULL;size_t data_size = 0;AVPacket *pkt = NULL;AVFrame *decoded_frame = NULL;if (argc <= 0){fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);exit(0);}filename = "believe.aac";outfilename = "believe.pcm";pkt = av_packet_alloc();// 如果需要解码视频,则修改为对应视频解码器IDenum AVCodecID audio_codec_id = AV_CODEC_ID_AAC;if(strstr(filename, "aac") != NULL){audio_codec_id = AV_CODEC_ID_AAC;}else if(strstr(filename, "mp3") != NULL){audio_codec_id = AV_CODEC_ID_MP3;}else{printf("default codec id:%d\n", audio_codec_id);}// 查找解码器codec = avcodec_find_decoder(audio_codec_id); // AV_CODEC_ID_AACif (!codec) {fprintf(stderr, "Codec not found\n");exit(1);}// 获取裸流的解析器 AVCodecParserContext(数据) + AVCodecParser(方法)parser = av_parser_init(codec->id);if (!parser) {fprintf(stderr, "Parser not found\n");exit(1);}// 分配codec上下文codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate audio codec context\n");exit(1);}// 将解码器和解码器上下文进行关联if (avcodec_open2(codec_ctx, codec, NULL) < 0) {fprintf(stderr, "Could not open codec\n");exit(1);}// 打开输入文件infile = fopen(filename, "rb");if (!infile) {fprintf(stderr, "Could not open %s\n", filename);exit(1);}// 打开输出文件outfile = fopen(outfilename, "wb");if (!outfile) {av_free(codec_ctx);exit(1);}// 读取文件进行解码data = inbuf;data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, infile);while (data_size > 0){if (!decoded_frame){if (!(decoded_frame = av_frame_alloc())){fprintf(stderr, "Could not allocate audio frame\n");exit(1);}}ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if (ret < 0){fprintf(stderr, "Error while parsing\n");exit(1);}data += ret; // 跳过已经解析的数据data_size -= ret; // 对应的缓存大小也做相应减小if (pkt->size)decode(codec_ctx, pkt, decoded_frame, outfile);if (data_size < AUDIO_REFILL_THRESH) // 如果数据少了则再次读取{memmove(inbuf, data, data_size); // 把之前剩的数据拷贝到buffer的起始位置data = inbuf;// 读取数据 长度: AUDIO_INBUF_SIZE - data_sizelen = fread(data + data_size, 1, AUDIO_INBUF_SIZE - data_size, infile);if (len > 0)data_size += len;}}/* 冲刷解码器 */pkt->data = NULL; // 让其进入drain modepkt->size = 0;decode(codec_ctx, pkt, decoded_frame, outfile);fclose(outfile);fclose(infile);avcodec_free_context(&codec_ctx);av_parser_close(parser);av_frame_free(&decoded_frame);av_packet_free(&pkt);printf("main finish, please enter Enter and exit\n");return 0;
}相关文章:
音视频实战---音视频解码
该方法只能解码裸流。 1、使用avcodec_find_decoder查找解码器 根据使用解码器类型,决定是解码音频还是解码视频。 2、 使用av_parser_init获取裸流解析器和方法 3、使用avcodec_alloc_context3分配编解码器上下文 4、使用avcodec_open2将解码器和解码器上下文…...
MyBatisPlus 之四:MP 的乐观锁和逻辑删除、分组、排序、链式的实现步骤
乐观锁 乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。 乐观锁适用…...
node.js常用的命令
Node.js 是一个用于执行 JavaScript 代码的运行时环境。以下命令是 Node.js 开发中常用的命令,可以帮助你进行包管理、项目配置和代码执行等操作。 node -v:检查 Node.js 的版本。npm -v:检查 npm(Node.js 包管理器)的…...
Python从入门到精通秘籍十
一、Python之了解异常 当在Python中执行代码时,如果发生错误,就会抛出异常(Exception)。处理异常是编写健壮的代码的重要部分。Python提供了try-except语句来捕获和处理异常。 下面是使用Python代码详细讲解异常处理的例子&…...
Android:adb命令
执行adb命令的窗口如下 Mac或Linux系统里的终端窗口; window系统运行输入cmd打开的指令窗口; Android Studio 里控制下面的Terminal窗口 1. 查看已链接的设备和模拟器 adb devices -l 2. 查看Android内核版本号 adb shell getprop ro.build.version.re…...
Github基本功能和使用技巧
基础功能 创建仓库(Repository):在GitHub上创建一个新的仓库,可以通过点击页面右上角的“New”按钮开始。选择仓库的名称、描述和许可证等信息,并选择是否将仓库设置为公开或私有。 克隆仓库(Clone&#x…...
mac上系统偏好里无法停止mysql
使用强制杀死进程: sudo kill -9 pid原文:https://www.cnblogs.com/yalong/p/14136997.html 命令行也没有关闭成功:https://blog.51cto.com/u_5018054/5101645...
launchctl及其配置、使用、示例
文章目录 launchctl 是什么Unix / Linux类似的工具有什么哪个更常用配置使用常用子命令示例加载一个 launch agent:卸载一个 launch daemon:列出所有已加载的服务:启动一个服务:停止一个服务:禁用一个服务:启用一个服务: 附com.example.myagent.plist内容有趣的例子参考 launch…...
如何在Ubuntu系统搭建Excalidraw容器并实现公网访问本地绘制流程图
文章目录 1. 安装Docker2. 使用Docker拉取Excalidraw镜像3. 创建并启动Excalidraw容器4. 本地连接测试5. 公网远程访问本地Excalidraw5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Ubuntu系统使用Docker部署开源白板工具Excal…...
PostgreSQL和MySQL的异同
0.前言 MySQL是一个关系数据库管理系统(DBMS),通过该系统,您可以将数据存储为包含行和列的二维表格。它是一个常用系统,支持许多 Web 应用程序、动态网站和嵌入式系统。PostgreSQL 是一个对象关系数据库管理系统&…...
有ai写文案的工具吗?分享5款好用的工具!
在数字化时代,人工智能(AI)已渗透到我们生活的方方面面,包括内容创作领域。AI写文案的软件以其高效、便捷的特点,正逐渐受到广大内容创作者、营销人员、甚至普通用户的青睐。本文将为您盘点几款热门的AI写文案软件&…...
docker+k8s相关面试题
dockerk8s k8s详细介绍docker的工作原理docker的组成docker与传统虚拟机的区别docker技术的三大核心概念centos镜像几个G,但是docker centos镜像才几百兆镜像的分层结构以及为什么要使用镜像的分层结构容器的copy-on-write特性,修改容器里面的内容会修改…...
力扣爆刷第101天之hot100五连刷91-95
力扣爆刷第101天之hot100五连刷91-95 文章目录 力扣爆刷第101天之hot100五连刷91-95一、62. 不同路径二、64. 最小路径和三、5. 最长回文子串四、1143. 最长公共子序列五、72. 编辑距离 一、62. 不同路径 题目链接:https://leetcode.cn/problems/unique-paths/desc…...
前端vue实现甘特图
1 什么是甘特图 甘特图(Gantt chart)又称为横道图、条状图(Bar chart)。以提出者亨利L甘特先生的名字命名,是项目管理、生产排程、节点管理中非常常见的一个功能。 甘特图内在思想简单,即以图示的方式通过活动列表和时间刻度形象地表示出任何特定项目的…...
SQLiteC/C++接口详细介绍之sqlite3类(十五)
返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(十四) 下一篇:SQLiteC/C接口详细介绍之sqlite3类(十六) 47.sqlite3_set_authorizer 用法ÿ…...
每日三个JAVA经典面试题(十八)
1.volatile 关键字的作用 在Java中,volatile关键字用于声明变量,以确保该变量的更新对所有线程都是可见的,即当一个线程修改了一个volatile变量的值,这个新值对于其他线程来说是立即得知的。volatile关键字有两个主要作用&#x…...
RPC 和 序列化
RPC 1 RPC调用流程 1.1 clerk客户端调用远程服务 Clerk::PutAppend() raftServerRpcUtil::PutAppend() raftServerRpcUtil是client与kvserver通信的入口, 包含kvserver功能的一对一映射:Get/PutAppend,通过stub对象——raftKVRpcProctoc:…...
【原创】三十分钟实时数据可视化网站前后端教程 Scrapy + Django + React 保姆级教程向
这个本来是想做视频的,所以是以讲稿的形式写的。最后没做视频,但是觉得这篇文还是值得记录一下。真的要多记录,不然一些不常用的东西即使做过几个月又有点陌生了。 文章目录 爬虫 SCRAPYxpath 后端 DJANGO前端 REACT Hello大家好这里是小鱼&a…...
MySQL的备份
为什么要备份: 1.保证重要的数据不丢失 2.数据转移 MySQL数据库备份的方式: 1.直接拷贝物理文件 2.在可视化工具中手动导出 (1)在想要导出的表或者数据库中,右键,选择备份或导出 使用命令行导出 MyS…...
Linux 磁盘的一生
注意:实验环境都是使用VMware模拟 磁盘接口类型这里vm中是SCSI,扩展sata,ide(有时间可以看看或者磁盘的历史) 总结:磁盘从有到无—类似于建房子到可以住 ————————————————————————————————————…...
终极指南:在Docker中快速部署Mermaid图表生成工具
终极指南:在Docker中快速部署Mermaid图表生成工具 【免费下载链接】mermaid-cli Command line tool for the Mermaid library 项目地址: https://gitcode.com/gh_mirrors/me/mermaid-cli 你是否经常需要将Mermaid图表代码转换为高质量的图像文件,…...
保姆级YOLO12部署指南:基于注意力机制的最新检测模型快速体验
保姆级YOLO12部署指南:基于注意力机制的最新检测模型快速体验 1. 模型简介 YOLO12是2025年发布的最新目标检测模型,由国际顶尖研究机构联合研发。该模型采用创新的注意力为中心架构,在保持实时推理速度的同时,实现了业界领先的检…...
解密WMM2025地磁模型:GeographicLib如何用12阶球谐函数重塑地球磁场计算
解密WMM2025地磁模型:GeographicLib如何用12阶球谐函数重塑地球磁场计算 【免费下载链接】geographiclib Main repository for GeographicLib 项目地址: https://gitcode.com/gh_mirrors/ge/geographiclib 你是否曾经好奇,为什么智能手机的指南针…...
QT记事本进阶——巧用QMap构建编码映射,实现ComboBox与QTextStream的无缝对接
1. 为什么需要编码映射? 在开发一个支持多编码的文本编辑器时,最头疼的问题之一就是如何让用户选择的编码名称(比如"UTF-8"、"GBK")能够正确转换为Qt内部的编码枚举值。这个问题在Qt 6.9之后变得更加突出&…...
终极Windows系统优化指南:用Win11Debloat三步搞定系统卡顿
终极Windows系统优化指南:用Win11Debloat三步搞定系统卡顿 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter an…...
FinBERT金融情感分析:如何用AI模型洞察市场情绪变化
FinBERT金融情感分析:如何用AI模型洞察市场情绪变化 【免费下载链接】finbert 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/finbert FinBERT是一款专门为金融文本设计的预训练NLP模型,能够准确分析财经新闻、研报和社交媒体中的情感…...
透视校正插值:三角形重心坐标在3D渲染中的关键应用
1. 为什么我们需要透视校正插值 想象一下你正在玩一款3D游戏,角色走过一片铺满砖块的地面。如果仔细观察,会发现靠近屏幕下方的砖块看起来比上方的更大——这就是透视效果在起作用。当3D场景通过摄像机投影到2D屏幕上时,距离摄像机更近的物体…...
基于51单片机的智能交通灯控制系统:从仿真原理图到模块化设计实战
1. 智能交通灯控制系统概述 十字路口的交通灯控制是城市交通管理的基础设施,传统固定时长的红绿灯已经无法满足现代交通需求。基于51单片机的智能交通灯控制系统,通过可编程控制实现了灵活的时间调度和多种工作模式。这个系统不仅包含了基本的红绿灯切换…...
Git核心概念与版本控制思想启蒙
Git核心概念与版本控制思想启蒙 那天下午,调试器停在一个诡异的堆栈溢出位置。我盯着屏幕上的十六进制地址,突然意识到——三小时前能正常运行的代码,现在彻底崩了。更糟糕的是,我完全想不起自己改过哪些文件。Ctrl+Z按到手酸,文件恢复对话框弹了又弹,最后只能对着编译错…...
OFA图文语义蕴含系统应用场景:AI驱动的内容安全审核方案
OFA图文语义蕴含系统应用场景:AI驱动的内容安全审核方案 1. 引言:当图文不符成为网络常态 你有没有遇到过这样的情况?刷社交媒体时,看到一张触目惊心的图片,配文讲述一个悲惨的故事,但仔细一看࿰…...
