FFmpeg-- mp4文件合成2:pcm和yuv编码(c++实现)

文章目录

      • 流程
        • 音频
        • 视频
      • api
      • 核心代码
        • audioencoder.h
        • audioencoder.cpp
        • videoencoder.h
        • videoencoder.cpp

pcm和yuv编码为aac和h264,封装为c++的AudioEncoder类和VideoEncoder类

流程

音频
  • 初始化音频参数
    int InitAAC(int channels, int sample_rate, int bit_rate);

  • 音频编码,pts需要转化为编码时的pts, 发送帧frame, 获取 packet
    AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);

  • 获取一帧数据通道号的采样点
    int GetFrameSize()

  • 获取编码器需要的采样格式
    int GetSampleFormat()

  • 释放资源
    void DeInit();

视频
  • 初始化视频参数
    int InitH264(int width, int height, int fps, int bit_rate);

  • 视频编码,pts需要转化为编码时的pts, 需要初始化AVFrame结构体,发送帧frame, 获取 packet
    AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);

  • 释放资源
    void DeInit();

api

  • 用于初始化一个AVFrame结构体,包括设置AVFrame中的各项参数,不需要重新分配buffer,需要传入一个指向AVFrame结构体的指针
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],const uint8_t *src,enum AVPixelFormat pix_fmt, int width, int height, int align);

核心代码

audioencoder.h
#ifndef AUDIOENCODER_H
#define AUDIOENCODER_Hextern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}
class AudioEncoder
{
public:AudioEncoder();~AudioEncoder();int InitAAC(int channels, int sample_rate, int bit_rate);
//    int InitMP3(/*int channels, int sample_rate, int bit_rate*/);void DeInit();  // 释放资源AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);int GetFrameSize(); // 获取一帧数据 每个通道需要多少个采样点int GetSampleFormat();  // 编码器需要的采样格式
private:int channels_ = 2;int sample_rate_ = 44100;int bit_rate_ = 128*1024;int64_t pts_ = 0;AVCodecContext * codec_ctx_ = NULL;
};#endif // AUDIOENCODER_H
audioencoder.cpp
#include "audioencoder.h"AudioEncoder::AudioEncoder()
{}AudioEncoder::~AudioEncoder()
{if(codec_ctx_) {DeInit();}
}int AudioEncoder::InitAAC(int channels, int sample_rate, int bit_rate)
{channels_ = channels;sample_rate_ = sample_rate;bit_rate_ = bit_rate;AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);if(!codec) {printf("avcodec_find_encoder AV_CODEC_ID_AAC failed\n");return -1;}codec_ctx_ = avcodec_alloc_context3(codec);if(!codec_ctx_) {printf("avcodec_alloc_context3 AV_CODEC_ID_AAC failed\n");return -1;}codec_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;codec_ctx_->bit_rate = bit_rate_;codec_ctx_->sample_rate = sample_rate_;codec_ctx_->sample_fmt = AV_SAMPLE_FMT_FLTP;codec_ctx_->channels = channels_;codec_ctx_->channel_layout = av_get_default_channel_layout(codec_ctx_->channels);int ret = avcodec_open2(codec_ctx_, NULL, NULL);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_open2 failed:%s\n", errbuf);return -1;}printf("InitAAC success\n");return 0;
}void AudioEncoder::DeInit()
{if(codec_ctx_) {avcodec_free_context(&codec_ctx_);  // codec_ctx_被设置为NULL
//        codec_ctx_ = NULL;  // 不需要再写}
}AVPacket *AudioEncoder::Encode(AVFrame *frame, int stream_index, int64_t pts, int64_t time_base)
{if(!codec_ctx_) {printf("codec_ctx_ null\n");return NULL;}pts = av_rescale_q(pts, AVRational{1, (int)time_base}, codec_ctx_->time_base);if(frame) {frame->pts = pts;}int ret = avcodec_send_frame(codec_ctx_, frame);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_send_frame failed:%s\n", errbuf);return NULL;}AVPacket *packet = av_packet_alloc();ret = avcodec_receive_packet(codec_ctx_, packet);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_receive_packet failed:%s\n", errbuf);av_packet_free(&packet);return NULL;}packet->stream_index = stream_index;return packet;
}int AudioEncoder::GetFrameSize()
{if(codec_ctx_)return codec_ctx_->frame_size;return 0;
}int AudioEncoder::GetSampleFormat()
{if(codec_ctx_)return codec_ctx_->sample_fmt;return -1;  // AV_SAMPLE_FMT_NONE
}
videoencoder.h
#ifndef VIDEOENCODER_H
#define VIDEOENCODER_H
extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}class VideoEncoder
{
public:VideoEncoder();~VideoEncoder();int InitH264(int width, int height, int fps, int bit_rate);void DeInit();AVPacket *Encode(uint8_t *yuv_data, int yuv_size,int stream_index, int64_t pts, int64_t time_base);private:int width_ = 0;int height_ = 0;int fps_ = 25;int bit_rate_ = 500*1024;int64_t pts_ = 0;AVCodecContext * codec_ctx_ = NULL;AVFrame *frame_ = NULL;
};#endif // VIDEOENCODER_H
videoencoder.cpp
#include "videoencoder.h"
extern "C"
{
#include "libavutil/imgutils.h"
}
VideoEncoder::VideoEncoder()
{}VideoEncoder::~VideoEncoder()
{if(codec_ctx_) {DeInit();}
}int VideoEncoder::InitH264(int width, int height, int fps, int bit_rate)
{width_ = width;height_ = height;fps_ = fps;bit_rate_ = bit_rate;AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);if(!codec) {printf("avcodec_find_encoder AV_CODEC_ID_H264 failed\n");return -1;}codec_ctx_ = avcodec_alloc_context3(codec);if(!codec_ctx_) {printf("avcodec_alloc_context3 AV_CODEC_ID_H264 failed\n");return -1;}codec_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;codec_ctx_->bit_rate = bit_rate_;codec_ctx_->width = width_;codec_ctx_->height = height_;codec_ctx_->framerate = {fps_, 1};codec_ctx_->time_base = {1, 1000000};   // 单位为微妙codec_ctx_->gop_size = fps_;codec_ctx_->max_b_frames = 0;codec_ctx_->pix_fmt = AV_PIX_FMT_YUV420P;int ret = avcodec_open2(codec_ctx_, NULL, NULL);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_open2 failed:%s\n", errbuf);return -1;}frame_ = av_frame_alloc();if(!frame_) {printf("av_frame_alloc failed\n");return -1;}frame_->width = width_;frame_->height = height_;frame_->format = codec_ctx_->pix_fmt;printf("Inith264 success\n");return 0;
}void VideoEncoder::DeInit()
{if(codec_ctx_) {avcodec_free_context(&codec_ctx_);}if(frame_) {av_frame_free(&frame_);}
}AVPacket *VideoEncoder::Encode(uint8_t *yuv_data, int yuv_size, int stream_index, int64_t pts, int64_t time_base)
{if(!codec_ctx_) {printf("codec_ctx_ null\n");return NULL;}int ret = 0;pts = av_rescale_q(pts, AVRational{1, (int)time_base}, codec_ctx_->time_base);frame_->pts = pts;if(yuv_data) {//该函数用于初始化一个AVFrame结构体,包括设置AVFrame中的各项参数,不需要重新分配buffer//使用该函数需要传入一个指向AVFrame结构体的指针int ret_size = av_image_fill_arrays(frame_->data, frame_->linesize,yuv_data, (AVPixelFormat)frame_->format,frame_->width, frame_->height, 1);if(ret_size != yuv_size) {printf("ret_size:%d != yuv_size:%d -> failed\n", ret_size, yuv_size);return NULL;}ret = avcodec_send_frame(codec_ctx_, frame_);} else {ret = avcodec_send_frame(codec_ctx_, NULL);}if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_send_frame failed:%s\n", errbuf);return NULL;}AVPacket *packet = av_packet_alloc();ret = avcodec_receive_packet(codec_ctx_, packet);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_receive_packet failed:%s\n", errbuf);av_packet_free(&packet);return NULL;}packet->stream_index = stream_index;return packet;
}

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

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

相关文章

手机抓包也太简单好玩了吧!

我们选择Charles来作为抓包工具,本文将从0到1讲解从电脑端抓包到手机端抓包。 Charles是一款被广泛使用的网络抓包工具,它可以用来监控和调试通过HTTP和HTTPS协议发送和接收的所有网络请求和响应。Charles通常用于网页和网络应用的开发过程中&#xff0…

mac上系统偏好里无法停止mysql

使用强制杀死进程: sudo kill -9 pid原文:https://www.cnblogs.com/yalong/p/14136997.html 命令行也没有关闭成功:https://blog.51cto.com/u_5018054/5101645

基于python+vue家政服务系统flask-django-php-nodejs

相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低家政公司的运营人员成本,实现了家政服务的标准化、制度化、程序化的管理,有效地防止了家政服务的随意管理,提高了信息的处理速度和精确度,能够及时、准确地…

9.测试教程-性能测试概述

文章目录 1.常见的性能问题2.为什么要进行性能测试3.性能测试实施的流程4.概念和术语介绍5.性能测试模型6.性能测试方法介绍7.性能测试实施与管理8.性能测试前期准备9.测试工具引入10.性能测试方案11.性能测试设计与开发12.性能测试设计与管理13.性能测试设计与调优14.性能测试…

【.net/.net core】后台生成echarts图片解决方案及.net core html转word方法

工具环境下载: EChartsConvert:https://gitee.com/saintlee/echartsconvert EChartsConvert为生成echarts图片的服务端,用于接收参数和生成echarts图表图片BASE64编码 PhantomJS:Download PhantomJS PhantomJS用来发布EChartsConvert服务…

在 3D 虚拟城市中展示自定义建筑

在本教程中,您将学习如何创建 Cesium 应用程序,用您自己的 3D 模型替换真实城市中的建筑物。您可以使用它来可视化拟建建筑的影响,及如何改变天际线?从特定楼层或房间看到的景色会是什么样子? 我们将介绍如何&#xf…

Web and HTTP

Web and HTTP First, a review… ▪ web page consists of objects ▪ object can be HTML file, JPEG image, Java applet, audio file,… ▪ web page consists of base HTML-file which includes several referenced objects ▪ each object is addressable by a URL, e.g.,…

MAC本安装telnet

Linux运维工具-ywtool 目录 1.打开终端1.先安装brew命令2.写入环境变量4.安装telnet 1.打开终端 访达 - 应用程序(左侧) - 实用工具(右侧) - 终端 #注意:登入终端用普通用户,不要用MAC的root用户1.先安装brew命令 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/H…

Databend x CubeFS:面向未来的企业级云原生数据存储与分析

用场景的丰富,企业面临着前所未有的数据存储挑战。大规模数据存储变得日常化,伴随着超大容量和快速变化的I/O需求,传统的存储解决方案已经难以满足企业对弹性、运维效率及总体拥有成本(TCO)的更高要求。这些挑战促使基…

基于傅里叶描述子的手势动作识别,Matlab实现

博主简介: 专注、专一于Matlab图像处理学习、交流,matlab图像代码代做/项目合作可以联系(QQ:3249726188) 个人主页:Matlab_ImagePro-CSDN博客 原则:代码均由本人编写完成,非中介,提供…

小米路由器4A千兆版刷回官方固件

原文链接:小米路由器4A千兆版刷回官方固件及修改SN绑定APP-小米无线路由器及小米网络设备-恩山无线论坛 (right.com.cn) 进入breed 由于openwrt工作不稳定,决定重新刷回官方固件。 由于当前路由器已经刷过breed,不再重新刷入。 如何刷入b…

数学建模(灰色关联度 python代码 案例)

目录 介绍: 模板: 案例:哪些原因影响结婚率 数据标准化: 灰色关联度系数: 完整代码: 结果: 介绍: 灰色关联度是一种多指标综合评价方法,用于分析和评价不同指标之…

QT编程实现播放器(一)ffmpeg库的编译

整体思想是使用ffmpeg库实现一款自己的播放器,该篇主要讲述ffmpeg的编译。在编译过程中出现很多问题进行记录。由于之前的播放器用ffmpeg-4.1.3在win11上无法正常工作,升级到4.3.6版本试试看。 目录 一、下载MSYS2 二、下载ffmpeg-4.3.6 x264-master …

由浅到深认识Java语言(9):Eclipse IDE简介

该文章Github地址:https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.c…

华为配置蓝牙终端定位实验

配置蓝牙终端定位示例 组网图形 图1 配置蓝牙终端定位示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 商场管理员希望在已有WLAN覆盖业务的基础上,使用蓝牙定位技术,根据顾客所在的位置,提供商场导航、导…

Node.js 命令行实战:从入门到精通

目录 第一章:Node.js 简介 1.1 Node.js 概述 1.2 Node.js 的特点 1.3 Node.js 的安装和配置 1.3.1 下载和安装 Node.js 1.3.2 验证安装 1.3.3 配置环境变量 1.4 Node.js 的运行环境 1.5 Node.js 的应用场景 1.6 小结 第二章:Node.js 命令行基础 2.1 命令行界面 (…

在ubuntu22.04.4安装freeswitch1.10.10

一、环境 No LSB modules are available. Distributor ID:      Ubuntu Description:         Ubuntu 22.04.4 LTS Release:             22.04.4 Codename:            jammy 二、依赖 1、 工具包 apt install -y openssh-server …

php 对接Vungle海外广告平台收益接口Reporting API

今天对接的是Vungle广告reporting api接口,拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到Vungle后台就能看到文档地址以及参数: 文档地址:https://support.vungle.com/hc/en-us/articles/211365828-Publisher-Reporting…

(c/c++)——线程的基础使用

文章目录 前言一、构造函数二、线程资源的回收三、公有成员函数3.1 get_id()3.2 operator=2.读入数据总结前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、构造函数 // 1)默认构造函,构造一个线程对象,不执行任何任务(不会创建/启动子线程) thread() noexcep…

AI助力生产制造质检,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建工业生产制造场景下的瓷砖瑕疵检测识别分析系统

瓷砖生产环节一般经过原材料混合研磨、脱水、压胚、喷墨印花、淋釉、烧制、抛光,最后进行质量检测和包装。得益于产业自动化的发展,目前生产环节已基本实现无人化。而质量检测环节仍大量依赖人工完成。一般来说,一条产线需要配数名质检工&…