视频重编码为h265重新封装MP4并截断

2023-11-11

MP4 重编码重封装-分辨率和编码格式(转为h265)调整

XFormat.h

#pragma once
#include <mutex>

struct AVFormatContext;
struct AVCodecParameters;
struct AVPacket;
struct AVCodecContext;

void PrintError(int err);

struct Rational 
{
	int num; ///< Numerator
	int den; ///< Denominator
};

class XFormat
{
public:
	XFormat();
	// 设置上下文,并且清理上次的设置的值,如果传递NULL,相当于关闭上下文3
	// 线程安全
	bool setContext(AVFormatContext* context);
	bool isVaild();
	int videoIndex();
	int audioIndex();
	Rational videoTimebase();
	Rational audioTimebase();
	bool copyParam(int index, AVCodecParameters* dst);
	bool copyParam(int index, AVCodecContext* dst);
	bool rescaleTime(AVPacket* packet, int offset_pts, Rational timebase);
	int codecId();

protected:
	AVFormatContext* m_context;		// 封装解封装上下文
	std::mutex m_mtx;
	int m_video_index;				// video和audio在stream中索引
	int m_audio_index;
	Rational m_video_timebase;
	Rational m_audio_timebase;
	int m_codec_id;
};

XFormat.cpp

#include "XFormat.h"
#include <iostream>

using namespace std;

extern "C"  // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C"
{
	// 引用 ffmpeg 头文件
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

// 预处理指令导入库
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")

void PrintError(int err);


XFormat::XFormat()
{
	m_context = nullptr;
	m_video_index = AVMEDIA_TYPE_VIDEO;
	m_audio_index = AVMEDIA_TYPE_AUDIO;
	m_video_timebase = { 1, 25 };
	m_audio_timebase = { 1, 9000 };
	m_codec_id = -1;
}

bool XFormat::setContext(AVFormatContext* context)
{
	bool ret = true;
	unique_lock<mutex> lock(m_mtx);
	
	if (m_context != nullptr)
	{
		if (m_context->oformat)			// 输出上下文
		{
			if (m_context->pb != nullptr)
			{
				avio_close(m_context->pb);
			}

			avformat_free_context(m_context);
		}
		else if (m_context->iformat)	//输入上下文
		{
			avformat_close_input(&m_context);
		}
	}

	m_context = context;

	if (m_context != nullptr)
	{
		//区分音视频stream 索引
		for (int i = 0; i < m_context->nb_streams; i++)
		{
			if (m_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
			{
				m_video_index = i;
				m_video_timebase.num = m_context->streams[i]->time_base.num;
				m_video_timebase.den = m_context->streams[i]->time_base.den;
				m_codec_id = m_context->streams[i]->codecpar->codec_id;
			}
			else if (m_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
			{
				m_audio_index = i;
				m_audio_timebase.num = m_context->streams[i]->time_base.num;
				m_audio_timebase.den = m_context->streams[i]->time_base.den;
			}
		}
	}

	return ret;
}

bool XFormat::isVaild()
{
	unique_lock<mutex> lock(m_mtx);

	return (m_context != nullptr);
}

int XFormat::videoIndex()
{
	return m_video_index;
}

int XFormat::audioIndex()
{
	return m_audio_index;
}

bool XFormat::copyParam(int index, AVCodecParameters* dst)
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if ((m_context != nullptr) && (index >= 0) && (index < m_context->nb_streams) && (dst != nullptr))
	{
		err = avcodec_parameters_copy(dst, m_context->streams[index]->codecpar);

		if (err >= 0)
		{
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

bool XFormat::copyParam(int index, AVCodecContext* dst)
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if ((m_context != nullptr) && (index >= 0) && (index < m_context->nb_streams) && (dst != nullptr))
	{
		err = avcodec_parameters_to_context(dst, m_context->streams[index]->codecpar);

		if (err >= 0)
		{
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

Rational XFormat::videoTimebase()
{
	return m_video_timebase;
}

Rational XFormat::audioTimebase()
{
	return m_audio_timebase;
}

bool XFormat::rescaleTime(AVPacket* packet, int offset_pts, Rational timebase)
{
	bool ret = false;
	int err = 0;
	int pts = 0;
	AVRational in_timebase = { 0 };
	AVRational out_timebase = { 0 };
	unique_lock<mutex> lock(m_mtx);

	if ((m_context != nullptr) && (packet != nullptr) && (offset_pts >= 0))
	{
		if (packet->stream_index == AVMEDIA_TYPE_VIDEO)
		{
			out_timebase = m_context->streams[AVMEDIA_TYPE_VIDEO]->time_base;
		}
		else if (packet->stream_index == AVMEDIA_TYPE_AUDIO)
		{
			out_timebase = m_context->streams[AVMEDIA_TYPE_AUDIO]->time_base;
		}

		in_timebase.num = timebase.num;
		in_timebase.den = timebase.den;

		packet->pts = av_rescale_q_rnd(packet->pts - offset_pts, in_timebase, out_timebase, static_cast<AVRounding>(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
		packet->dts = av_rescale_q_rnd(packet->dts - offset_pts, in_timebase, out_timebase, static_cast<AVRounding>(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
		packet->duration = av_rescale_q(packet->duration, in_timebase, out_timebase);
		packet->pos = -1;

		ret = true;
	}

	return ret;
}

int XFormat::codecId()
{
	return m_codec_id;
}

XDemux.h

#pragma once
#include "XFormat.h"

class XDemux : public XFormat
{
public:
	// 打开解封装
	static AVFormatContext* Open(const char* url);
	// 读取一帧数据
	bool read(AVPacket* packet);
	bool seek(long long begin_pts, int stream_index);
};

XDemux.cpp

#include "XDemux.h"
#include <iostream>

using namespace std;

extern "C"  // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C"
{
	// 引用 ffmpeg 头文件
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

AVFormatContext* XDemux::Open(const char* url)
{
	AVFormatContext* ret = nullptr;
	int err = 0;

	if (url != nullptr)
	{
		err = avformat_open_input(&ret, url,nullptr,nullptr);

		if (err == 0)
		{
			err = avformat_find_stream_info(ret, nullptr);

			if (err >= 0)
			{
				av_dump_format(ret, 0, url, 0);
			
			}
			else
			{
				PrintError(err);
				avformat_free_context(ret);
			}
		}
		else
		{
			PrintError(err);
			ret = nullptr;
		}
	}

	return ret;
}

bool XDemux::read(AVPacket* packet)
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if (m_context != nullptr)
	{
		err = av_read_frame(m_context, packet);

		if (err >= 0)
		{
			ret = true;
		}
	}

	return ret;
}

bool XDemux::seek(long long begin_pts, int stream_index)
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if ((m_context != nullptr) && (stream_index >= 0))
	{
		ret = av_seek_frame(m_context, stream_index, begin_pts, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD);	// 向后关键帧

		if (err >= 0)
		{
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

XMux.h

#pragma once
#include "XFormat.h"
class XMux : public XFormat
{
public:
	static AVFormatContext* Open(const char* url);
	bool writeHead();
	bool write(AVPacket* packet);
	bool writeEnd();
};

XMux.cpp

#include "XMux.h"
#include <iostream>

using namespace std;

extern "C"  // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C"
{
	// 引用 ffmpeg 头文件
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

AVFormatContext* XMux::Open(const char* url)
{
	AVFormatContext* ret = nullptr;
	int err = 0;

	if (url != nullptr)
	{
		err = avformat_alloc_output_context2(&ret, nullptr, nullptr, url);

		if (err >= 0)
		{
			avformat_new_stream(ret, nullptr);
			avformat_new_stream(ret, nullptr);

			err = avio_open(&ret->pb, url, AVIO_FLAG_WRITE);

			if (err < 0)
			{
				PrintError(err);

				avformat_free_context(ret);
				ret = nullptr;
			}
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

bool XMux::writeHead()
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if (m_context != nullptr)
	{
		ret = avformat_write_header(m_context, nullptr);

		if (err == 0)
		{
			//打印输出上下文
			av_dump_format(m_context, 0, m_context->url, 1);
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

bool XMux::write(AVPacket* packet)
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if (m_context != nullptr)
	{
		// 写入一帧数据,内部缓冲排序dts,通过pkt=null 可以写入缓冲
		ret = av_interleaved_write_frame(m_context, packet);

		if (err == 0)
		{
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

bool XMux::writeEnd()
{
	bool ret = false;
	int err = 0;
	unique_lock<mutex> lock(m_mtx);

	if (m_context != nullptr)
	{
		// 写入排序缓冲
		av_interleaved_write_frame(m_context, nullptr);
		ret = av_write_trailer(m_context);

		if (err == 0)
		{
			ret = true;
		}
		else
		{
			PrintError(err);
		}
	}

	return ret;
}

125_test_xformat.cpp

#include <iostream>
#include "XDemux.h"
#include "XMux.h"
#include "XDecode.h"
#include "XEncode.h"

using namespace std;

extern "C"  // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C"
{
	// 引用 ffmpeg 头文件
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

// 预处理指令导入库
#pragma comment(lib, "avcodec.lib")


#define CERR(err)  if(err != 0)				\
					{						\
						PrintError(err);	\
						return -1;			\
					}

int main(int argc, char* argv[])
{
	int ret = 0;
	AVFormatContext* ic = nullptr;  // 解封装输入上下文
	const char* url = "v1080.mp4";
	AVPacket packet;
	AVFormatContext* oc = nullptr;
	const char* out_url = "test_remux.mp4";
	const char* in_file = nullptr;
	const char* out_file = nullptr;
	int begin_sec = 0;
	int end_sec = 0;
	long long begin_video_pts = 0;
	long long begin_audio_pts = 0;
	long long end_video_pts = 0;
	XDemux demux;
	XMux mux;
	int video_count = 0;	// 视频帧数量
	int audio_count = 0;	// 音频帧数量
	double total_sec = 0;	// 视频总时长
	int video_width = 0;	// 视频宽度
	int video_height = 0;	// 视频高度
	XDecode de;
	XEncode en;
	AVCodecContext* decode_c = nullptr;
	AVCodecContext* encode_c = nullptr;
	AVFrame* frame = nullptr;
	AVPacket* en_pkt = nullptr;


	if (argc < 3)
	{
		cout << "usage: program in_file.mp4 out_file.mp4 <begin_sec> <end_sec> <video_width> <video_height>" << endl;
		cout << "example: 124_test_xformat v1080.mpt test.mp4 10 20 400 300" << endl;

		return -1;
	}

	in_file = argv[1];
	out_file = argv[2];

	if (argc > 3)
	{
		begin_sec = atoi(argv[3]);
	}

	if (argc > 4)
	{
		end_sec = atoi(argv[4]);
	}

	if (argc > 5)
	{
		video_width = atoi(argv[5]);
	}

	if (argc > 6)
	{
		video_height = atoi(argv[6]);
	}

	ic = demux.Open(url);
	demux.setContext(ic);

	oc = mux.Open(out_url);

	decode_c = de.Create(demux.codecId(), false);
	demux.copyParam(demux.videoIndex(), decode_c);
	de.setContext(decode_c);
	de.open();
	frame = de.createFrame();

	if (video_width <= 0)
	{
		video_width = ic->streams[demux.videoIndex()]->codecpar->width;
	}

	if (video_height <= 0)
	{
		video_height = ic->streams[demux.videoIndex()]->codecpar->height;
	}

	encode_c = en.Create(AV_CODEC_ID_H265, true);
	encode_c->pix_fmt = AV_PIX_FMT_YUV420P;
	encode_c->width = video_width;
	encode_c->height = video_height;
	en.setContext(encode_c);
	en.open();

	// 设置编码音视频流参数
	if (demux.isVaild() && (demux.videoIndex() >= 0))
	{
		oc->streams[mux.videoIndex()]->time_base.num = demux.videoTimebase().num;  // 时间基数与原视频一致
		oc->streams[mux.videoIndex()]->time_base.den = demux.videoTimebase().den;
		avcodec_parameters_from_context(oc->streams[mux.videoIndex()]->codecpar, encode_c);
	}

	if (demux.isVaild() && (demux.videoIndex() >= 0))
	{
		oc->streams[mux.audioIndex()]->time_base.num = demux.videoTimebase().num;
		oc->streams[mux.audioIndex()]->time_base.den = demux.videoTimebase().den;
		demux.copyParam(demux.audioIndex(), oc->streams[mux.audioIndex()]->codecpar);
	}

	mux.setContext(oc);

	mux.writeHead();

	if (demux.isVaild() && (demux.videoTimebase().num > 0))
	{
		double t = (double)demux.videoTimebase().den / (double)demux.videoTimebase().num;

		begin_video_pts = begin_sec * t;
		end_video_pts = end_sec * t;
	}

	if (demux.isVaild() && (demux.audioTimebase().num > 0))
	{
		double t = (double)demux.audioTimebase().den / (double)demux.audioTimebase().num;

		begin_audio_pts = begin_sec * t;
	}


	demux.seek(begin_video_pts, 0);

	while (1)
	{
		if (!demux.read(&packet))  // 此函数不会是否 packet 中原先的 buf 空间,需要手动调用 av_packet_unref 来释放 buf 空间
		{
			break;
		}

		if (packet.stream_index == AVMEDIA_TYPE_VIDEO)
		{
			if (packet.pts > end_video_pts)
			{
				av_packet_unref(&packet);
				break;
			}

			video_count++;
			total_sec += (double)packet.duration * mux.videoTimebase().num / mux.videoTimebase().den;
			mux.rescaleTime(&packet, begin_video_pts, demux.videoTimebase());

			if (de.send(&packet))
			{
				while (de.recv(frame))
				{
					if ((en_pkt = en.encode(frame)) != nullptr)
					{
						en_pkt->stream_index = mux.videoIndex();
						mux.write(en_pkt);
						av_packet_free(&en_pkt);
					}
				}
			}
		}
		else if (packet.stream_index == AVMEDIA_TYPE_AUDIO)
		{
			audio_count++;
			mux.rescaleTime(&packet, begin_audio_pts, demux.audioTimebase());

			if (!mux.write(&packet))
			{
				break;
			}
		}
	}

	// 写入结尾 包含文件偏移索引
	mux.writeEnd();

	av_frame_free(&frame);
	en.setContext(nullptr);
	de.setContext(nullptr);
	mux.setContext(nullptr);
	demux.setContext(nullptr);

	cout << "视频帧数: " << video_count << endl;
	cout << "音频帧数: " << audio_count << endl;
	cout << "视频时长: " << total_sec << endl;

	return 0;
}

这个代码的作用:首先对mp4文件进行解封装,根据用户的输入的开始截断时间和结束截断时间,对视频进行截断,截断时需要重新设置 packet 的 pts dts 和 duration。然后将 packet 解码出 frame,使用编码器对 frame 进行编码,编码器为 H265 编码方式,图像编码的长和宽可以根据用户的输入来决定,编码出 packet 以后,最后进行封装,封装为处理后的mp4文件。

编码后的视频效果如下图所示:

原视频的尺寸为 1920x1080,编码时所使用的尺寸为 800x600,所以视频只有左上角显示了。 

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

视频重编码为h265重新封装MP4并截断 的相关文章

  • UAC协议基础第一篇: UAC类设备相关的描述符

    目录 一 描述符 1 设备描述符 2 配置描述符 2 1 配置描述符集合的总长度
  • FFmpeg中的常见结构体

    代码基于FFmpeg5 0 1 目录 FFFormatContext AVFormatContext AVIOContext FFIOContext URLContext URLProtocol AVInputFormat FFStream
  • 【ElementUI组件】视频上传+计算视频时长

    效果如下 实现步骤 1 首先先安装官网的操作步骤安装elementui 或者 不安装直接引入 安装指令 npm i element ui S 引入方式 2 以下是参考代码 HTML代码 div div
  • 视频转码后有色差要如何处理

    目录 视频转码后有色差要如何处理 KEY COLOR STANDARD KEY COLOR RANGE 视频转码后有色差要如何处理 以下是回答 欢迎大家留言讨论补充 1 色差是如何产生的 1 有损压缩产生的质量损失 解决方法为尽可能的提高码
  • 【操作教程】EasyNVR平台如何接入硬盘录像机?

    EasyNVR是基于RTSP Onvif协议接入的视频平台 可支持将前端设备的音视频进行采集 传输 处理并分发 实现视频监控直播 云端录像 云存储 检索回看 国标级联 告警等视频能力 平台兼容性高 可拓展性强 性能稳定 可应用在智慧工地 智
  • unity和ffmpeg修改局部视频速度

    unity版本2020 3 17 前言 最近有个功能是 在一个展馆里面 有一个摄像头旋转拍照 拍一圈 本来功能很简单 就录屏就可以了上传生成二维码就ok了 但是 需要一个视频中间快两边变慢的效果 查了很多资料 最终决定使用ffmpeg和un
  • Android:播放UDP流例如udp://@239.0.0.3:8218

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

    前言 随着新冠疫情的影响 这两年音视频的需求呈爆发式增长 在音视频领域中 WebRTC可以说是一个绕不开宝库 包括了音视频采集 编解码 传输 渲染的全过程 本文主要记录下在Mac平台上编译WebRTC Mac和iOS版本的全过程 设置代理
  • vue3中实现音频播放器APlayer

    前言 vue2的时候 分享了一个很好用的插件是vue aplayer 但是他是不支持vue3的 这里分享vue3使用APlayer来实现一个播放器的方法 实现效果 官方 git地址 点我 api地址 点我 实现步骤 1 安装 npm npm
  • 音视频学习笔记(雷神)—技术解析

    音视频技术解析 封装技术 视频压缩编解码 音频压缩编解码 这是技术层 流媒体传输协议 这是网络层 视频播放器解析 解协议 从视频播放器的角度做解析 拿到传输而来的视频数据后 首先要解协议 传输协议 自然的本地视频经过硬盘传输数据自然没有解协
  • 【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部分怎么保存或者使用呢
  • 浅谈音视频开发入门基础及进阶资源分享

    导言 音视频开发涉及的知识面比较广 知识点又相对独立琐碎 入门门槛相对较高 想要对音视频开发具有深入全面的了解 需要在行业深耕多年 本文将简单介绍音视频的采集 编解码 传输 渲染四个技术点并对涉及到的知识点和原理进行解释 希望你可以对音视频
  • 音视频的功耗优化

    前言 在应用中 录制与音视频模块往往是高耗能的模块 设备容易发热 影响体验 什么是功耗优化 手机有多个耗电模块 SOC CPU GPU DDR Display Audio Video Camera WIFI 等 通过参数配置优化 代码优化等
  • 【毕设项目】视频人像背景替换器-抠出视频中人像到动态背景中去

    描述 环境 简而言之 使用人体语义分割实现抠图替换动态背景 首先毫无疑问就是环境配置 附上链接 开始使用 飞桨 源于产业实践的开源深度学习平台 paddlepaddle org cn https www paddlepaddle org c
  • 中国首家!腾讯云入选Gartner®视频平台服务市场指南代表厂商

    近日 Gartner正式发布 Market Guide for Video Platform Services 视频平台服务市场指南 下称 指南 凭借领先的音视频技术和产品组合优势 腾讯云成为中国首家且唯一入选的代表厂商 腾讯云VPS一站式
  • 免费音效素材网站,一次性介绍清楚

    不管是在游戏 电影 电视剧 短视频还是音频中 合适的音效能够更好的表达内容和渲染氛围 今天给大家分享几个免费音效素材 感兴趣的话可以接着往下看 一 制片帮素材 找音效 制片帮素材不仅有海量的优质视频素材 还有丰富的音效资源 分类清晰 更重要
  • 电动车低速提示音系统(AVAS)

    随着电动汽车的迅速发展 以及电动汽车的保有量也越来越多 根据车辆的特征来说电动汽车相比于传统的内燃机汽车要安静 为了保护行人 减少事故的发生 欧盟最近发布了一项关于电动车的新法规 自2019年7月1日开始 欧盟关于电动汽车的最新法律正式生效
  • 教育场景数字化中音视频小程序的发展

    教育场景数字化逐步成为刚需 2018年以来 国家对在线教育行业的监管收紧 以及受益于 5G 技术的发展 教育科技逐步走向成熟化和规范化 教育行业的本质是人与人 老师与学生 老师与家长 以及更多角色直接的沟通与互动 而仅仅是古早式的在线文字已
  • 有没有实用的视频、图片素材网站推荐?

    在作品创作中 素材网站扮演着至关重要的角色 它们提供了海量的设计资源 为设计师 艺术家和创意工作者提供了无限的可能性 本文将为您介绍几款备受推崇的素材网站 帮助您开启创意之旅 一 制片帮素材 制片帮素材是一个提供海量精品视频素材的网站 站内

随机推荐

  • 虚拟环境安装和操作

    文章目录 安装相应库和配置 查看已安装虚拟环境 创建虚拟环境 切换 进入虚拟环境 退出虚拟环境 虚拟环境 linux创建Python虚拟环境及配置 Django Flask项目中如何创建Python虚拟环境呢 汇总 环境迁移 安装相应库和配
  • 攻防世界MISC刷题1-50

    目录 1 ext3 2 base64stego 3 功夫再高也怕菜刀 4 easycap 5 reverseMe 6 Hear with your Eyes 7 What is this 8 normal png 9 something i
  • idea 添加 VUE 的语法支持和开发

    一 VUE的开发分两种 一种是直接在HTML文件中使用 一种是VUE文件的形式开发 1 首先我们先让 HTML 文件支持 VUE 的语法指令提示 2 File gt Setting gt Edit gt Inspections gt htm
  • 父类A a = new 子类B

    父类名 a new 子类名 子类名 b new 子类名 比较上面两种创建实例的区别 a只能调用父类的函数 和子类重写父类的方法 不能调用父类中不存在的子类的函数 因为它没有继承 a是父类的引用 指向了一个子类对象 好处如果一旦发现该B对象无
  • Jetson Orin NX install Fastdeploy

    FastDeploy jetson md at develop PaddlePaddle FastDeploy GitHub sudo apt get install gcc sudo apt get install cmake git c
  • postman-token的作用

    Postman生成的代码中的postman token是什么 What is the postman token in generated code from Postman 这主要用于绕过Chrome 等其他浏览器 中的错误 如果XMLH
  • QEMU/KVM PCI Passthrough(i350) & DPDK 网络性能测试

    QEMU KVM PCI Passthrough i350 DPDK 网络性能测试 硬件要求 CPU必须支持硬件虚拟化 Intel VT d or AMD Vi 和 IOMMU 原图链接 主机配置 设置iommu IOMMU kernel
  • kmp算法(最简单最直观的理解,看完包会)

    本文将以特殊的方式来让人们更好地理解kmp算法 不包括kmp算法的推导 接下来 我们将从朴素算法出发 在这之前 我们先设主串为S 模式串为T 我们要解决的询问是主串中是否包含模式串 即T是否为S的子串 版权声明 本文为原创文章 转载请标明出
  • c++ 继承 学习总结1 继承的基本语法

    前言 继承的作用是减少程序中重复的代码段 如果程序中有很多重复的代码段 可以考虑一下能否使用继承 继承的语法 class 子类 继承方式 父类 include
  • 特征提取-特征工程

    目录 1 定义 2 字典特征提取 3 英文 本特征提取 4 中文 本特征提取 1 定义 将任意数据 如 本或图像 转换为可 于机器学习的数字特征 2 字典特征提取 from sklearn feature extraction import
  • 【算法】树状数组维护总结

    本文仅对树状数组的使用作一个总结 并非讲解 这里的操作都对长度为 n n n 的数组 a a a 进行操作 单点修改 区间查询 暴力做法 修改
  • java使用原始套接字技术进行数据包截获_Linux零拷贝技术,看完这篇文章就懂了...

    本文讲解 Linux 的零拷贝技术 云计算是一门很庞大的技术学科 融合了很多技术 Linux 算是比较基础的技术 所以 学好 Linux 对于云计算的学习会有比较大的帮助 本文借鉴并总结了几种比较常见的 Linux 下的零拷贝技术 相关的引
  • python的pyecharts绘制各种图表详细(代码)

    环境 pyecharts库 echarts countries pypkg echarts china provinces pypkg echarts china cities pypkg 数据 2018年4月16号的全国各地最高最低和天气
  • 5.5js

    1 JavaScript简介 什么是JavaScript JavaScript 是 种客户端脚本语 脚本语 是 种轻量级的编程语 JavaScript 通常被直接嵌 HTML 由浏览器解释执 JavaScript 是 种解释性语 就是说 代
  • Deepin 手动分区记录

    起初安装Deepin 采用手动分区 总是安装失败 经过以下分区就成功安装了 efi 分区 默认300m boot 分区 默认 512m 交换分区 swap 等于你的内存大小 分区 15G home 分区剩余全部容量 home可以设置也可以不
  • brpc组件bvar源码解析(三)Variable、Reducer和Adder

    1 Variable类 Variable是所有bvar的基类 是一个纯虚类 拥有的唯一的成员变量是 name Variable类中的接口分为几类 描述相关的 子类实现纯虚函数describe 目的是将bvar的值写入ostream get
  • 验证码倒计时

    获取验证码倒计时 return second 120 getCodeFn let flag true if this user phone this http isPhone this user phone false this http
  • 斐讯 K2 路由器 无线中继 无线扩展设置教程图文

    斐讯 K2 路由器无线扩展设置教程 1 连接上k2路由器无线网络 2 登录k2路由器管理页面 192 168 2 1 3 上网设置 4 无线设置 5 设置k2无线扩展功能 6 选择主路由器无线网络 7 设置无线网络信息wifi名称 wifi
  • 详解redis的哨兵模式(1)

    目录 1 背景 2 实现过程 2 1 初始化服务器 2 2 将普通Redis服务器使用的代码替换成Sentinel专用代码 2 3初始化Sentinel状态 2 4初始化sentinel状态的masters属性 2 5创建连向主服务器的网络
  • 视频重编码为h265重新封装MP4并截断

    MP4 重编码重封装 分辨率和编码格式 转为h265 调整 XFormat h pragma once include