windows下使用FFmpeg开源库进行视频编解码完整步聚
最终解码效果:

1.UI设计
2.在控件属性窗口中输入默认值

3.复制已编译FFmpeg库到工程同级目录下
4.在工程引用FFmpeg库及头文件

5.链接指定FFmpeg库
6.使用FFmpeg库
引用头文件
extern "C"
{
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/bsf.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavutil/imgutils.h"
#include "libavutil/log.h"
#include "libavutil/imgutils.h"
#include "libavutil/time.h"
#include <libswresample/swresample.h>}
创建视频编解码管理类

实现视频编解码管理类
#include "ffmpegmananger.h"
#include <QThread>
ffmpegMananger::ffmpegMananger(QObject *parent ):QObject(parent)
{m_pInFmtCtx = nullptr;m_pTsFmtCtx = nullptr;m_qstrRtspURL = "";m_qstrOutPutFile = "";
}
ffmpegMananger::~ffmpegMananger()
{avformat_free_context(m_pInFmtCtx);avformat_free_context(m_pTsFmtCtx);
}void ffmpegMananger::getRtspURL(QString strRtspURL)
{this->m_qstrRtspURL = strRtspURL;
}
void ffmpegMananger::getOutURL(QString strRute)
{this->m_qstrOutPutFile = strRute;printf("===========%s\n",m_qstrOutPutFile.toStdString().c_str());
}
void ffmpegMananger::setOutputCtx(AVCodecContext *encCtx, AVFormatContext **pTsFmtCtx,int &nVideoIdx_out)
{avformat_alloc_output_context2(pTsFmtCtx , nullptr, nullptr, m_qstrOutPutFile.toStdString().c_str());if (!pTsFmtCtx ) {printf("Could not create output context\n");return;}if (avio_open(&((*pTsFmtCtx)->pb), m_qstrOutPutFile.toStdString().c_str(), AVIO_FLAG_READ_WRITE) < 0){avformat_free_context(*pTsFmtCtx);printf("avio_open fail.");return;}AVStream *out_stream = avformat_new_stream(*pTsFmtCtx, encCtx->codec);nVideoIdx_out = out_stream->index;//nVideoIdx_out = out_stream->index;avcodec_parameters_from_context(out_stream->codecpar, encCtx);printf("==========Output Information==========\n");av_dump_format(*pTsFmtCtx, 0, m_qstrOutPutFile.toStdString().c_str(), 1);printf("======================================\n");
}
int ffmpegMananger::ffmepgInput()
{int nRet = 0;AVCodecContext *encCtx = nullptr;//编码器//const char *pUrl = "D:/videos/264.dat";std::string temp = m_qstrRtspURL.toStdString();const char *pUrl = temp.c_str();printf("===========%s\n",pUrl);AVDictionary *options = nullptr;av_dict_set(&options,"rtsp_transport", "tcp", 0);av_dict_set(&options,"stimeout","10000000",0);// 设置“buffer_size”缓存容量av_dict_set(&options, "buffer_size", "1024000", 0);nRet = avformat_open_input(&m_pInFmtCtx,pUrl,nullptr,&options);if( nRet < 0){printf("Could not open input file,===========keep trying \n");return nRet;}avformat_find_stream_info(m_pInFmtCtx, nullptr);printf("===========Input Information==========\n");av_dump_format(m_pInFmtCtx, 0, pUrl, 0);printf("======================================\n");//1.获取视频流编号int nVideo_indx = av_find_best_stream(m_pInFmtCtx,AVMEDIA_TYPE_VIDEO,-1,-1,nullptr,0);if(nVideo_indx < 0){avformat_free_context(m_pInFmtCtx);printf("查找解码器失败\n");return -1;}//2.查找解码器AVCodec *pInCodec = avcodec_find_decoder(m_pInFmtCtx->streams[nVideo_indx]->codecpar->codec_id);if(nullptr == pInCodec){printf("avcodec_find_decoder fail.");return -1;}//获取解码器上下文AVCodecContext* pInCodecCtx = avcodec_alloc_context3(pInCodec);//复制解码器参数nRet = avcodec_parameters_to_context(pInCodecCtx, m_pInFmtCtx->streams[nVideo_indx]->codecpar);if(nRet < 0){avcodec_free_context(&pInCodecCtx);printf("avcodec_parameters_to_context fail.");return -1;}//打开解码器if(avcodec_open2(pInCodecCtx, pInCodec, nullptr) < 0){avcodec_free_context(&pInCodecCtx);printf("Error: Can't open codec!\n");return -1;}printf("width = %d\n", pInCodecCtx->width);printf("height = %d\n", pInCodecCtx->height);int frame_index = 0;int got_picture = 0;AVStream *in_stream =nullptr;AVStream *out_stream =nullptr;AVFrame *pFrame= av_frame_alloc();AVPacket *newpkt = av_packet_alloc();AVPacket *packet = av_packet_alloc();av_init_packet(newpkt);av_init_packet(packet);// alloc AVFrameAVFrame*pFrameRGB = av_frame_alloc();// 图像色彩空间转换、分辨率缩放、前后图像滤波处理SwsContext *m_SwsContext = sws_getContext(pInCodecCtx->width, pInCodecCtx->height,pInCodecCtx->pix_fmt, pInCodecCtx->width, pInCodecCtx->height,AV_PIX_FMT_RGB32, SWS_BICUBIC, nullptr, nullptr, nullptr);int bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, pInCodecCtx->width, pInCodecCtx->height,4);uint8_t *m_OutBuffer = (uint8_t *)av_malloc(bytes * sizeof(uint8_t));// 将分配的内存空间给pFrameRGB使用avpicture_fill((AVPicture *)pFrameRGB, m_OutBuffer, AV_PIX_FMT_RGB32, pInCodecCtx->width, pInCodecCtx->height);if(encCtx == nullptr){//打开编码器openEncoder(pInCodecCtx->width, pInCodecCtx->height,&encCtx);}int videoindex_out = 0;//设置输出文件上下文setOutputCtx(encCtx,&m_pTsFmtCtx,videoindex_out);//Write file headerif (avformat_write_header(m_pTsFmtCtx, nullptr) < 0){avformat_free_context(m_pTsFmtCtx);printf("Error occurred when opening output file\n");return -1;}printf("==============writer trail===================.\n");int count = 0;nRet = 0;while(av_read_frame(m_pInFmtCtx, packet) >= 0)//从pInFmtCtx读H264数据到packet;{if(packet->stream_index != nVideo_indx)//仅保留图像{continue;}if(avcodec_send_packet(pInCodecCtx, packet)<0)//送packet中H264数据给解码器码器进行解码,解码好的YUV数据放在pInCodecCtx,{break;}av_packet_unref(packet);got_picture = avcodec_receive_frame(pInCodecCtx, pFrame);//把解码好的YUV数据放到pFrame中if(0 == got_picture)//解码好一帧数据{//发送显示图像的信号// 对解码视频帧进行缩放、格式转换等操作sws_scale(m_SwsContext, (uint8_t const * const *)pFrame->data,pFrame->linesize, 0, pInCodecCtx->height,pFrameRGB->data, pFrameRGB->linesize);// 转换到QImageQImage tmmImage((uchar *)m_OutBuffer, pInCodecCtx->width, pInCodecCtx->height, QImage::Format_RGB32);QImage image = tmmImage.copy();// 发送QImageemit Sig_GetOneFrame(image);setDecoderPts(newpkt->stream_index,count, pFrame);count++;//送原始数据给编码器进行编码nRet = avcodec_send_frame(encCtx,pFrame);if(nRet < 0){continue;}//从编码器获取编号的数据while(nRet >= 0){nRet = avcodec_receive_packet(encCtx,newpkt);if(nRet < 0){break;}setEncoderPts(nVideo_indx,frame_index,videoindex_out,newpkt);int _count = 1;printf("Write %d Packet. size:%5d\tpts:%lld\n", _count,newpkt->size, newpkt->pts);if (av_interleaved_write_frame(m_pTsFmtCtx, newpkt) < 0){printf("Error muxing packet\n");goto end;}_count++;av_packet_unref(newpkt);}}}while(1)//从pInFmtCtx读H264数据到packet;{if(packet->stream_index != nVideo_indx)//仅保留图像{continue;}if(avcodec_send_packet(pInCodecCtx, packet)<0)//送packet中H264数据给解码器码器进行解码,解码好的YUV数据放在pInCodecCtx,{continue;}av_packet_unref(packet);got_picture = avcodec_receive_frame(pInCodecCtx, pFrame);//把解码好的YUV数据放到pFrame中if(!got_picture)//解码好一帧数据{AVRational in_time_base1 = in_stream->time_base;in_stream = m_pInFmtCtx->streams[newpkt->stream_index];//Duration between 2 frames (us)int64_t in_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);pFrame->pts = (double)(count*in_duration) / (double)(av_q2d(in_time_base1)*AV_TIME_BASE);count++;//送原始数据给编码器进行编码nRet = avcodec_send_frame(encCtx,pFrame);if(nRet < 0){break;}//从编码器获取编号的数据while(nRet >= 0){nRet = avcodec_receive_packet(encCtx,newpkt);if(nRet < 0){continue;}in_stream = m_pInFmtCtx->streams[newpkt->stream_index];out_stream = m_pTsFmtCtx->streams[videoindex_out];if (newpkt->stream_index == nVideo_indx){//FIX:No PTS (Example: Raw H.264)//Simple Write PTSif (newpkt->pts == AV_NOPTS_VALUE){//Write PTSAVRational time_base1 = in_stream->time_base;//Duration between 2 frames (us)int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);//Parametersnewpkt->pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE);newpkt->dts = newpkt->pts;newpkt->duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE);frame_index++;}}//Convert PTS/DTSnewpkt->pts = av_rescale_q_rnd(newpkt->pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));newpkt->dts = av_rescale_q_rnd(newpkt->dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));newpkt->duration = av_rescale_q(newpkt->duration, in_stream->time_base, out_stream->time_base);newpkt->pos = -1;newpkt->stream_index = videoindex_out;int count = 1;printf("Write %d Packet. size:%5d\tpts:%lld\n", count,newpkt->size, newpkt->pts);if (av_interleaved_write_frame(m_pTsFmtCtx, newpkt) < 0){printf("Error muxing packet\n");goto end;}count++;av_packet_unref(newpkt);}}}//Write file trailerav_write_trailer(m_pTsFmtCtx);
end:av_frame_free(&pFrame);av_frame_free(&pFrameRGB);av_packet_unref(newpkt);av_packet_unref(packet);std::cout<<"rtsp's h264 to ts end"; return 0;
}
void ffmpegMananger::setDecoderPts(int idx,int count,AVFrame *pFrame)
{AVStream* in_stream = m_pInFmtCtx->streams[idx];AVRational in_time_base1 = in_stream->time_base;//Duration between 2 frames (us)int64_t in_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);pFrame->pts = (double)(count*in_duration) / (double)(av_q2d(in_time_base1)*AV_TIME_BASE);
}
void ffmpegMananger::setEncoderPts(int nVideo_indx,int frame_index,int videoindex_out,AVPacket *newpkt)
{AVStream*in_stream = m_pInFmtCtx->streams[newpkt->stream_index];AVStream*out_stream = m_pTsFmtCtx->streams[videoindex_out];if (newpkt->stream_index == nVideo_indx){//FIX:No PTS (Example: Raw H.264)//Simple Write PTSif (newpkt->pts == AV_NOPTS_VALUE){//Write PTSAVRational time_base1 = in_stream->time_base;//Duration between 2 frames (us)int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);//Parametersnewpkt->pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE);newpkt->dts = newpkt->pts;newpkt->duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE);frame_index++;}}//Convert PTS/DTSnewpkt->pts = av_rescale_q_rnd(newpkt->pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));newpkt->dts = av_rescale_q_rnd(newpkt->dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));newpkt->duration = av_rescale_q(newpkt->duration, in_stream->time_base, out_stream->time_base);newpkt->pos = -1;newpkt->stream_index = videoindex_out;
}
void ffmpegMananger::writeTail()
{//Write file trailerav_write_trailer(m_pTsFmtCtx);
}
void ffmpegMananger::openEncoder(int width, int height, AVCodecContext** enc_ctx)
{//使用libx264编码器AVCodec * pCodec = avcodec_find_encoder_by_name("libx264");if(nullptr == pCodec){printf("avcodec_find_encoder_by_name fail.\n");return;}//获取编码器上下文*enc_ctx = avcodec_alloc_context3(pCodec);if(nullptr == enc_ctx){printf("avcodec_alloc_context3(pCodec) fail.\n");return;}//sps/pps(*enc_ctx)->profile = FF_PROFILE_H264_MAIN;(*enc_ctx)->level = 30;//表示level是5.0//分辨率(*enc_ctx)->width = width;(*enc_ctx)->height = height;//gop(*enc_ctx)->gop_size = 25;//i帧间隔(*enc_ctx)->keyint_min = 20;//设置最小自动插入i帧的间隔.OPTION//B帧(*enc_ctx)->max_b_frames = 0;//不要B帧(*enc_ctx)->has_b_frames = 0;////参考帧(*enc_ctx)->refs = 3;//OPTION//设置输入的yuv格式(*enc_ctx)->pix_fmt = AV_PIX_FMT_YUV420P;//设置码率(*enc_ctx)->bit_rate = 3000000;//设置帧率//(*enc_ctx)->time_base = (AVRational){1,25};//帧与帧之间的间隔(*enc_ctx)->time_base.num = 1;(*enc_ctx)->time_base.den = 25;//(*enc_ctx)->framerate = (AVRational){25,1};//帧率 25帧每秒(*enc_ctx)->framerate.num = 25;(*enc_ctx)->framerate.den = 1;if(avcodec_open2((*enc_ctx),pCodec,nullptr) < 0){printf("avcodec_open2 fail.\n");}return;
}
相关文章:
windows下使用FFmpeg开源库进行视频编解码完整步聚
最终解码效果: 1.UI设计 2.在控件属性窗口中输入默认值 3.复制已编译FFmpeg库到工程同级目录下 4.在工程引用FFmpeg库及头文件 5.链接指定FFmpeg库 6.使用FFmpeg库 引用头文件 extern "C" { #include "libswscale/swscale.h" #include "libavdevic…...
如何更改eclipse的JDK版本
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、有时候导入一些网上的资源需要更换JDK二、使用步骤1. 总结 一、有时候导入一些网上的资源需要更换JDK 具体操作如下 二、使用步骤 1. 在eclipse上方工具栏找…...
HarmonyOS第一课运行Hello World
前言 俗话说,工欲善其事必先利其器。鸿蒙第一课,我们先从简单的Hello World运行说起。要先运行Hello World,那么我们必须搭建HarmonyOS的开发环境。 下载与安装DevEco Studio 在HarmonyOS应用开发学习之前,需要进行一些准备工作&a…...
解决el-tooltip滚动时悬浮框相对位置发生变化
获取最外层box的class,并在内层添加el-scrollbar <template><div class"ChartsBottom"><el-scrollbar><ul class""><li v-for"(item, index) in list" :key"index"><div class"con…...
Java精品项目源码第61期汽车零件销售商城系统(代号V063)
Java精品项目源码第61期汽车零件销售商城系统(代号V063) 大家好,小辰今天给大家介绍一个汽车零件销售商城系统,演示视频公众号(小辰哥的Java)对号查询观看即可 文章目录 Java精品项目源码第61期汽车零件销售商城系统(代号V063)难…...
Python OpenCV剪裁图片并修改对应的Labelme标注文件
Python OpenCV剪裁图片并修改对应的Labelme标注文件 前言前提条件相关介绍实验环境剪裁图片并修改对应的Labelme标注文件代码实现 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-P…...
【JAVA学习笔记】44 - 注解,元注解
项目代码 一、注解的引入 1)注解(Annotation)也被称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。 2)和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。 3)在Ja…...
Android 安卓Kotlin-协程
当谈到现代异步编程时,Kotlin协程(Kotlin Coroutines)是一个备受欢迎的工具。它提供了一种更具可读性和可维护性的方式来处理异步任务,而无需陷入回调地狱。本篇博客将深入探讨Kotlin协程,涵盖其基本概念、用法、特性以…...
SSO 系统设计_token 生成
SSO 系统设计_token 生成 目录概述需求: 设计思路实现思路分析1.增加依赖2.代码编写3.测试 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wai…...
电表安数大小和省电有关吗?
电表的安数是指电表能够正常工作的电流范围,通常用来表示电表的容量。电表的安数越大,表示电表能够承受的电流就越大。电表的安数与省电之间并没有直接的关系,但是电表的安数大小会影响到电表的准确性和稳定性。如果电表的安数太小࿰…...
树上形态改变统计贡献:1025T4
http://cplusoj.com/d/senior/p/SS231025D 答案为 ∑ w [ x ] − w [ s o n [ x ] ] \sum w[x]-w[son[x]] ∑w[x]−w[son[x]], x x x 非儿子 要维护断边,LCT固然可以,但不一定需要 发现如果发生了变化,只会由重儿子变成次重儿子…...
如何处理与智能床相关的医疗建议和医疗器械证明?
如何处理与智能床相关的医疗建议和医疗器械证明? 摘要:作为一名iOS技术博主,我遇到了一个困扰,我的应用在审核中被拒绝了。这次拒绝涉及到我们公司生产的智能床,该床收集用户的体征数据并提供睡眠建议。苹果指出我们未…...
云原生之深入解析如何合并多个kubeconfig文件
项目通常有多个 k8s 集群环境,dev、testing、staging、prod,kubetcl 在多个环境中切换,操作集群 Pod 等资源对象,前提条件是将这三个环境的配置信息都写到本地机的 $HOME/.kube/config 文件中。默认情况下kubectl会查找$HOME/.kub…...
Netty实战-实现自己的通讯框架
通信框架功能设计 功能描述 通信框架承载了业务内部各模块之间的消息交互和服务调用,它的主要功能如下: 基于 Netty 的 NIO 通信框架,提供高性能的异步通信能力;提供消息的编解码框架,可以实现 POJO 的序列化和反序…...
S4.2.4.3 Electrical Idle Sequence(EIOS)
一 本章节主讲知识点 1.1 EIOS的具体码型 1.2 EIOS的识别规则 1.3 EIEOS的具体码型 二 本章节原文翻译 当某种状态下,发送器想要进入电器空闲状态的时候,发送器必须发送EIOSQ,也既是:电器Electrical Idle Odered Set Sequenc…...
MySQL的优化利器:索引条件下推,千万数据下性能提升273%
MySQL的优化利器:索引条件下推,千万数据下性能提升273%🚀 前言 上个阶段,我们聊过MySQL中字段类型的选择,感叹不同类型在千万数据下的性能差异 时间类型:MySQL字段的时间类型该如何选择?千万…...
回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测
回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-BiLSTM贝叶斯优化双向长…...
SOCKS5代理在全球电商、游戏及网络爬虫领域的技术创新
随着全球化进程的加速,跨界电商和游戏行业的出海战略愈发重要。在这个大背景下,技术如SOCKS5代理和网络爬虫成为连接不同领域、优化用户体验和提升市场竞争力的重要桥梁。本文将深入探讨SOCKS5代理技术在跨界电商、游戏和网络爬虫领域的应用及其对行业发…...
Flutter extended_image库设置内存缓存区大小与缓存图片数
ExtendedImage ExtendedImage 是一个Flutter库,用于提供高级图片加载和显示功能。这个库使用了 image 包来进行图片的加载和缓存。如果你想修改缓存大小,你可以通过修改ImageCache的配置来实现。 1. 获取ImageCache实例: 你可以通过PaintingBinding…...
第2篇 机器学习基础 —(1)机器学习概念和方式
前言:Hello大家好,我是小哥谈。机器学习是一种人工智能的分支,它使用算法和数学模型来使计算机系统能够从经验数据中学习和改进,而无需显式地编程。机器学习的目标是通过从数据中发现模式和规律,从而使计算机能够自动进…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
