视频重编码为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并截断 的相关文章

  • Nginx、FFmpeg实现浏览器无插件播放大华IPC、NVR设备视频

    Nginx FFmpeg实现浏览器无插件播放大华IPC NVR设备视频 使用Nginx FFmpeg将rtsp流转换为hls流 web页面通过video js实现视频播放 一 软件安装 1 安装Nginx Windows平台下 下载Ngin
  • UE4的视频播放(Media Player)

    1 视频播放Begining 首先将需要播放的视频拖入 创建Media Player和Media Texture 创建Material 将材质改为User Interface 在UI界面 创建Image 将这个材质装入 在人物Pawn界面添
  • HDMI之EDID使用说明

    Q1 为什么要写这篇文章 A1 在最近的工作中遇到了不少问题 其中很多都是和EDID相关的 可以说 作为一家以 显示 为生的企业 我们时时刻刻在与EDID打交道 EDID这东西很简单 但是如果不了解其基本原理和概念的话 会给我们的工作带来不
  • 6 FFmpeg从入门到精通-FFmpeg滤镜使用

    1 FFmpeg从入门到精通 FFmpeg简介 2 FFmpeg从入门到精通 FFmpeg工具使用基础 3 FFmpeg从入门到精通 FFmpeg转封装 4 FFmpeg从入门到精通 FFmpeg转码 5 FFmpeg从入门到精通 FFmp
  • 视频转码后有色差要如何处理

    目录 视频转码后有色差要如何处理 KEY COLOR STANDARD KEY COLOR RANGE 视频转码后有色差要如何处理 以下是回答 欢迎大家留言讨论补充 1 色差是如何产生的 1 有损压缩产生的质量损失 解决方法为尽可能的提高码
  • Android:播放UDP流例如udp://@239.0.0.3:8218

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

    OpenCV实战 29 视频对象追踪 0 前言 1 追踪视频中的对象 2 中值流追踪器算法原理 3 完整代码 小结 系列链接 0 前言 我们已经学习了如何跟踪图像序列中点和像素的运动 但在多数应用中 通常要求追踪视频中的特定移动对象 首先确
  • windows下使用FFmpeg生成YUV视频文件并播放(通过命令的方式)

    一 YUV的定义 YUV是一种颜色编码方法 它跟我们常见的RGB格式区分开来 常使用在各个视频处理组件中 其中 Y 代表明亮度 U 和 V 代表其色度 视频播放器把市面上流行的MP4等格式文件的视频部分解码出来 得到的一般会是YUV格式的数
  • uniapp使用uni.createInnerAudioContext()播放指定音频并且切换

    uniapp使用uni createInnerAudioContext播放指定音频并且切换 注意 效果图 主要代码 放上所有的代码 注意 uniapp API 中 uni createInnerAudioContext 是无法多音频播放的
  • 基于FFmpeg和Screen Capturer Recorder实现屏幕和声音的录制

    当我们看到一些精彩的视频画面 但无法下载时 可以通过录屏的方式将视频和音频录制下来 这个时候我们需要安装采集视频和音频的工具screen capture recorder 以下是在windows10环境下 基于FFmpeg和Screen C
  • 【ffmpeg基础】ffmpeg音频编码

    一 aac编码 输入raw音频编码为AAC ffmpeg i input wav acodec aac y input aac 通过 acodec来指定音频编码器 视频编码器为 vcodec 也可以使用 c a来指定音频编码器 ffmpeg
  • FFMPEG进阶系列02-ffmpeg命令详解3

    文章目录 ffmpeg 的封装转换 ffmpeg的编转码 ffmpeg 的基本编转码原理 过滤器链 filter chain 码率 帧率和文件大小 帧率 帧率和文件大小 调整视频分辨率 调整视频分辨率 scale filter调整分辨率 裁
  • HDMI CEC协议

    1 前言 本文档仅作为本人记录使用 主要根据工作使用及 HDMI Specification 1 4a pdf 进行终结得出 若有不足会后续补充 2 CEC简介 CEC Consumer Electronics Control 是一套完整的
  • 高效转码工具Compressor for Mac,让视频处理更轻松

    在现如今的数字时代 视频内容已经成为人们生活中不可或缺的一部分 无论是在社交媒体上分享生活点滴 还是在工作中制作专业的营销视频 我们都希望能够以高质量 高效率地处理和传输视频文件 而Compressor for Mac作为一款强大的视频转码
  • nodejs基于vue的视频分享投稿商城播放系统617bx

    本视频播放系统的设计目标是为用户提供一个便利的视频播放平台 同时系统融入投稿 商城以及论坛等功能模块 更全面的为用户提供服务 本文重点阐述了视频播放系统的开发过程 以实际运用为开发背景 基于vue框架 B S结构 运用了nodejs技术和M
  • 嵌入式开发、C++后端开发、C++音视频开发怎么选择?

    嵌入式开发 C 后端开发和C 音视频开发的选择问题 近年来 随着互联网和物联网的快速发展 嵌入式开发 C 后端开发和C 音视频开发等职业领域也逐渐受到广泛关注 对于有志于从事这些领域的人来说 如何做出选择呢 下面将从前景 薪酬和职业稳定性等
  • 音频转换mp3格式软件哪个好?下面推荐几款好用的软件给你

    你是否曾经遇到过这样的情况 下载了大量音频文件 却因为文件格式受到限制 而无法直接在设备上播放 不用担心 今天我将向大家介绍几款能把音频转换mp3的软件 它们可以帮助我们有效地解决音频格式不兼容的问题 一 专业的音频处理软件 优点1 简单易
  • 【音视频 | AAC】AAC音频编码详解

    博客主页 https blog csdn net wkd 007 博客内容 嵌入式开发 Linux C语言 C 数据结构 音视频 本文内容 介绍AAC音频编码 金句分享 你不能选择最好的 但最好的会来选择你 泰戈尔 本文未经允许 不得转发
  • 电动车低速提示音系统(AVAS)

    随着电动汽车的迅速发展 以及电动汽车的保有量也越来越多 根据车辆的特征来说电动汽车相比于传统的内燃机汽车要安静 为了保护行人 减少事故的发生 欧盟最近发布了一项关于电动车的新法规 自2019年7月1日开始 欧盟关于电动汽车的最新法律正式生效
  • 光端机技术综述:从理论到实践的全面探索

    在当今数据驱动的时代 光端机技术 已成为通信领域的核心组成部分 从理论的深度研究到实践的广泛应用 光端机技术不断推动着信息社会的发展 成为连接不同设备和网络的关键技术 技术特点 高速数据传输 光端机 利用光纤传输数据 具有极高的传输速率 相

随机推荐

  • 虚拟环境安装和操作

    文章目录 安装相应库和配置 查看已安装虚拟环境 创建虚拟环境 切换 进入虚拟环境 退出虚拟环境 虚拟环境 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