flutter开发实战-ijkplayer视频播放器功能

flutter开发实战-ijkplayer视频播放器功能

使用better_player播放器进行播放视频时候,在Android上会出现解码失败的问题,better_player使用的是video_player,video_player很多视频无法解码。最终采用ijkplayer播放器插件,在flutter上使用fijkplayer插件。
在这里插入图片描述
在这里插入图片描述

一、引入fijkplayer

在使用fijkplayer前可以先看下https://fijkplayer.befovy.com/docs/zh/fijkplayer-api.html

在工程的pubspec.yaml中引入插件

  fijkplayer: ^0.11.0

fijkPlayer 就是对 native C 层 ijkplayer 的一个 dart 包装,接口都保持一致。 FijkPlayer 处理所有播放相关的工作,实际工作都是由 native C 层 ijkplayer 完成,包含检查 dataSource 中的媒体信息,打开解码器和解码线程、打开音频输出设备、将解码后数据输出给音频设备或显示设备。

二、使用fijkplayer

2.1、IJKVideoPlayerController控制常用操作

使用fijkplayer,这里创建了IJKVideoPlayer来嵌套一下FijkView,使用IJKVideoPlayerController来控制常用功能操作

IJKVideoPlayerController如下

import 'dart:async';class IJKVideoPlayerController {FutureOr Function()? stop;FutureOr Function()? pause;FutureOr Function()? play;FutureOr Function(int msec)? seekTo;FutureOr Function(double volume)? setVolume;FutureOr Function(double speed)? setSpeed;FutureOr Function(int loopCount)? setLoop;FutureOr Function()? isPlaying;
}

IJKVideoPlayerController来控制停止、暂停、播放、seek、设置音量、设置播放速率、设置循环次数、获取是否在播放中等。

  • 播放视频
  void play() {if (videoPlayerController.play != null) {videoPlayerController.play!.call();}}
  • 暂停视频播放
  void pause() {if (videoPlayerController.pause != null) {videoPlayerController.pause!.call();}}
  • 停止视频播放
  void stop() {if (videoPlayerController.stop != null) {videoPlayerController.stop!.call();}}
  • seek指定位置
  void seekTo(int msec) {if (videoPlayerController.seekTo != null) {videoPlayerController.seekTo!.call(msec);}}
  • 设置音量
  void setVolume(double volume) {if (videoPlayerController.setVolume != null) {videoPlayerController.setVolume!.call(volume);}}
  • 设置播放速率
  void setSpeed(double speed) {if (videoPlayerController.setSpeed != null) {videoPlayerController.setSpeed!.call(speed);}}
  • 设置循环次数
  void setLoop(int loopCount) {if (videoPlayerController.setLoop != null) {videoPlayerController.setLoop!.call(loopCount);}}
  • 获取是否播放中
  Future<bool?> isPlaying() async {if (videoPlayerController.isPlaying != null) {bool videoIsPlaying = await videoPlayerController.isPlaying!.call();return videoIsPlaying;}return Future.value(null);}

2.2、在ijkplayer设置source,使用FijkPlayer

在设置播放器的时候,需要设置source类型。fijkplayer提供了两种方式,一种是本地工程文件、一种是网络视频地址。

  • 设置网络视频源
  /// usage/// autoPlay 为 true 时等同于连续调用 setDataSource、prepareAsync、startfplayer.setDataSource("http://samplevideo.com/sample.flv", autoPlay: true);
  • 设置本地资源作为播放源
  /// pubspec.yml 中需要指定assets 内容///   assets:///     - assets/butterfly.mp4////// scheme 是 `asset`, `://` 是 scheme 分隔符, `/` 是路径起始符号fplayer.setDataSource("asset:///assets/butterfly.mp4", autoPlay: true);

在setDataSource还有autoPlay(自动播放),showCover(是否显示视频封面,视频默认获取第一帧作为视频封面)

2.3、FijkView显示视频的控件Widget

在fijkplayer中,使用FijkView来显示视频。

  FijkView({required this.player,this.width,this.height,this.fit = FijkFit.contain,this.fsFit = FijkFit.contain,this.panelBuilder = defaultFijkPanelBuilder,this.color = const Color(0xFF607D8B),this.cover,this.fs = true,this.onDispose,});

可以设置显示fit、全屏的fit、背景颜色color、封面图(设置之后会显示在视频播放的上面)、是否全屏等。

在这里我们如果需要自定义样式,可以替换掉panelBuilder。

2.4、自定义控件IJKVideoPanel

在这里我们如果需要自定义样式,可以替换掉panelBuilder。我们自定义一个IJKVideoPanel,这个大部分代码来源default,这里调整了部分样式。

IJKVideoPanel完整代码如下

import 'dart:async';
import 'dart:math';import 'package:fijkplayer/fijkplayer.dart';
import 'package:flutter/material.dart';class IJKVideoPanel extends StatefulWidget {const IJKVideoPanel({super.key,required this.player,required this.buildContext,required this.viewSize,required this.texturePos,});final FijkPlayer player;final BuildContext buildContext;final Size viewSize;final Rect texturePos;@overrideState<IJKVideoPanel> createState() => _IJKVideoPanelState();
}class _IJKVideoPanelState extends State<IJKVideoPanel> {FijkPlayer get player => widget.player;Duration _duration = Duration();Duration _currentPos = Duration();Duration _bufferPos = Duration();bool _playing = false;bool _prepared = false;String? _exception;// bool _buffering = false;double _seekPos = -1.0;StreamSubscription? _currentPosSubs;StreamSubscription? _bufferPosSubs;//StreamSubscription _bufferingSubs;Timer? _hideTimer;bool _hideStuff = true;double _volume = 1.0;final barHeight = 40.0;@overridevoid initState() {super.initState();_duration = player.value.duration;_currentPos = player.currentPos;_bufferPos = player.bufferPos;_prepared = player.state.index >= FijkState.prepared.index;_playing = player.state == FijkState.started;_exception = player.value.exception.message;// _buffering = player.isBuffering;player.addListener(_playerValueChanged);_currentPosSubs = player.onCurrentPosUpdate.listen((v) {setState(() {_currentPos = v;});});_bufferPosSubs = player.onBufferPosUpdate.listen((v) {setState(() {_bufferPos = v;});});}void _playerValueChanged() {FijkValue value = player.value;if (value.duration != _duration) {setState(() {_duration = value.duration;});}bool playing = (value.state == FijkState.started);bool prepared = value.prepared;String? exception = value.exception.message;if (playing != _playing ||prepared != _prepared ||exception != _exception) {setState(() {_playing = playing;_prepared = prepared;_exception = exception;});}}void _playOrPause() {if (_playing == true) {player.pause();} else {player.start();}}@overridevoid dispose() {super.dispose();_hideTimer?.cancel();player.removeListener(_playerValueChanged);_currentPosSubs?.cancel();_bufferPosSubs?.cancel();}void _startHideTimer() {_hideTimer?.cancel();_hideTimer = Timer(const Duration(seconds: 3), () {setState(() {_hideStuff = true;});});}void _cancelAndRestartTimer() {if (_hideStuff == true) {_startHideTimer();}setState(() {_hideStuff = !_hideStuff;});}Widget _buildVolumeButton() {IconData iconData;if (_volume <= 0) {iconData = Icons.volume_off;} else {iconData = Icons.volume_up;}return IconButton(icon: Icon(iconData, color: Colors.white),padding: EdgeInsets.only(left: 10.0, right: 10.0),onPressed: () {setState(() {_volume = _volume > 0 ? 0.0 : 1.0;player.setVolume(_volume);});},);}AnimatedOpacity _buildBottomBar(BuildContext context) {double duration = _duration.inMilliseconds.toDouble();double currentValue =_seekPos > 0 ? _seekPos : _currentPos.inMilliseconds.toDouble();currentValue = min(currentValue, duration);currentValue = max(currentValue, 0);return AnimatedOpacity(opacity: _hideStuff ? 0.0 : 0.8,duration: Duration(milliseconds: 400),child: Container(height: barHeight,decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.transparent, Colors.black45],begin: Alignment.topCenter,end: Alignment.bottomCenter,),),child: Row(children: <Widget>[_buildVolumeButton(),Padding(padding: EdgeInsets.only(right: 5.0, left: 5),child: Text('${_duration2String(_currentPos)}',style: TextStyle(fontSize: 14.0, color: Colors.white),),),_duration.inMilliseconds == 0? Expanded(child: Center()): Expanded(child: Padding(padding: EdgeInsets.only(right: 0, left: 0),child: FijkSlider(value: currentValue,cacheValue: _bufferPos.inMilliseconds.toDouble(),min: 0.0,max: duration,onChanged: (v) {_startHideTimer();setState(() {_seekPos = v;});},onChangeEnd: (v) {setState(() {player.seekTo(v.toInt());print("seek to $v");_currentPos =Duration(milliseconds: _seekPos.toInt());_seekPos = -1;});},),),),// duration / position_duration.inMilliseconds == 0? Container(child: const Text("LIVE")): Padding(padding: EdgeInsets.only(right: 5.0, left: 5),child: Text('${_duration2String(_duration)}',style: TextStyle(fontSize: 14.0, color: Colors.white),),),//             IconButton(
//               icon: Icon(widget.player.value.fullScreen
//                   ? Icons.fullscreen_exit
//                   : Icons.fullscreen),
//               padding: EdgeInsets.only(left: 10.0, right: 10.0),
// //              color: Colors.transparent,
//               onPressed: () {
//                 widget.player.value.fullScreen
//                     ? player.exitFullScreen()
//                     : player.enterFullScreen();
//               },
//             )//],),),);}@overrideWidget build(BuildContext context) {// Rect rect = player.value.fullScreen//     ? Rect.fromLTWH(0, 0, widget.viewSize.width, widget.viewSize.height)//     : Rect.fromLTRB(//     max(0.0, widget.texturePos.left),//     max(0.0, widget.texturePos.top),//     min(widget.viewSize.width, widget.texturePos.right),//     min(widget.viewSize.height, widget.texturePos.bottom));Rect rect =Rect.fromLTWH(0, 0, widget.viewSize.width, widget.viewSize.height);return Positioned.fromRect(rect: rect,child: GestureDetector(onTap: _cancelAndRestartTimer,child: AbsorbPointer(absorbing: _hideStuff,child: Column(children: <Widget>[Container(height: barHeight),Expanded(child: GestureDetector(onTap: () {_cancelAndRestartTimer();},child: Container(color: Colors.transparent,height: double.infinity,width: double.infinity,child: Center(child: _exception != null? Text(_exception!,style: TextStyle(color: Colors.white,fontSize: 25,),): (_prepared ||player.state == FijkState.initialized)? AnimatedOpacity(opacity: _hideStuff ? 0.0 : 0.85,duration: Duration(milliseconds: 400),child: IconButton(iconSize: barHeight * 2,icon: Icon(_playing? Icons.pause: Icons.play_arrow,color: Colors.white,size: 44,),padding: EdgeInsets.only(left: 10.0, right: 10.0),onPressed: _playOrPause)): SizedBox(width: barHeight * 1.5,height: barHeight * 1.5,child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.white)),)),),),),_buildBottomBar(context),],),),),);}
}String _duration2String(Duration duration) {if (duration.inMilliseconds < 0) return "-: negtive";String twoDigits(int n) {if (n >= 10) return "$n";return "0$n";}String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));int inHours = duration.inHours;return inHours > 0? "$inHours:$twoDigitMinutes:$twoDigitSeconds": "$twoDigitMinutes:$twoDigitSeconds";
}

2.5、嵌套FijkView的IJKVideoPlayer

在使用时候,使用了IJKVideoPlayer来封装了一层FijkView。
在IJKVideoPlayer中设置了videoPlayerController控制播放的操作 如停止、暂停、播放、seek、设置音量、设置播放速率、设置循环次数、获取是否在播放中。

IJKVideoPlayer完整代码如下

  import 'package:fijkplayer/fijkplayer.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_demolab/ijk_player/ijk_video_panel.dart';import 'ijk_video_player_controller.dart';/// usage
/// autoPlay 为 true 时等同于连续调用 setDataSource、prepareAsync、start
/// fplayer.setDataSource("http://samplevideo.com/sample.flv", autoPlay: true);
///
/// 设置本地资源作为播放源,
/// pubspec.yml 中需要指定assets 内容
///   assets:
///     - assets/butterfly.mp4
///
/// scheme 是 `asset`, `://` 是 scheme 分隔符, `/` 是路径起始符号
/// fplayer.setDataSource("asset:///assets/butterfly.mp4", autoPlay: true);class IJKVideoPlayer extends StatefulWidget {const IJKVideoPlayer({super.key,required this.path,this.autoPlay = false,this.showCover = true,this.fit = FijkFit.contain,this.cover,this.color = Colors.black,this.width,this.height,this.videoPlayerController,});final double? width;final double? height;final String path;final bool autoPlay;final bool showCover;final FijkFit fit;final Widget? cover;final Color color;final IJKVideoPlayerController? videoPlayerController;@overrideState<IJKVideoPlayer> createState() => _IJKVideoPlayerState();
}class _IJKVideoPlayerState extends State<IJKVideoPlayer> {final FijkPlayer player = FijkPlayer();@overridevoid initState() {super.initState();player.setDataSource(widget.path,autoPlay: widget.autoPlay,showCover: widget.showCover,);addVideoPlayerFun();}void addVideoPlayerFun() {if (widget.videoPlayerController != null) {widget.videoPlayerController!.play = () {// 触发播放player.start();};widget.videoPlayerController!.stop = () {// 触发停止player.stop();};widget.videoPlayerController!.pause = () {// 触发暂停player.pause();};widget.videoPlayerController!.setLoop = (int loopCount) {// 触发setLoopif (loopCount < 0) {loopCount = 1;}player.setLoop(loopCount);};widget.videoPlayerController!.seekTo = (int msec) {// 触发seekif (msec < 0) {msec = 0;}player.seekTo(msec);};widget.videoPlayerController!.setVolume = (double volume) {// 触发setVolumeif (volume < 0.0) {volume = 0.0;}player.setVolume(volume);};widget.videoPlayerController!.setSpeed = (double speed) {// 触发setSpeedif (speed < 0.0) {speed = 1.0;}player.setSpeed(speed);};widget.videoPlayerController!.isPlaying = () {// 触发setVolumeif (FijkState.started == player.state) {return true;} else {return false;}};}}@overridevoid dispose() {super.dispose();player.release();}void onIJKDispose(FijkData fijkData) {}@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: Stack(alignment: Alignment.center,children: [widget.cover != null ? widget.cover! : Container(),FijkView(width: widget.width,height: widget.height,player: player,fit: widget.fit,fsFit: widget.fit,color: widget.color,onDispose: onIJKDispose,panelBuilder: (FijkPlayer player, FijkData data,BuildContext context, Size viewSize, Rect texturePos) {return IJKVideoPanel(player: player,buildContext: context,viewSize: viewSize,texturePos: texturePos,);},),],),);}
}

三、最后使用IJKVideoPlayer的IJKVideoPage页面

这里我创建了一个IJKVideoPage来使用IJKVideoPlayer视频播放,IJKVideoPlayer中需要path与videoPlayerController

IJKVideoPage完整代码如下

  import 'dart:async';import 'package:flutter/material.dart';import 'ijk_player/ijk_video_player.dart';
import 'ijk_player/ijk_video_player_controller.dart';class IJKVideoPage extends StatefulWidget {const IJKVideoPage({super.key,required this.url,});final String url;@overrideState<IJKVideoPage> createState() => _IJKVideoPageState();
}class _IJKVideoPageState extends State<IJKVideoPage> {final IJKVideoPlayerController videoPlayerController =IJKVideoPlayerController();@overridevoid initState() {super.initState();}@overrideWidget build(BuildContext context) {Size size = MediaQuery.of(context).size;return Scaffold(appBar: AppBar(title: Text("Fijkplayer Example")),body: Center(child: Container(width: size.width,height: size.width * 9.0 / 16.0,alignment: Alignment.center,child: IJKVideoPlayer(path: widget.url,videoPlayerController: videoPlayerController,color: Colors.black,),),),);}@overridevoid dispose() {super.dispose();}
}

如果外面的页面跳转到播放页面,需要设置url

  void testIJKVideoPage(BuildContext context) {Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {return IJKVideoPage(url: "https://vd2.bdstatic.com/mda-maif0tt1rirqp27q/540p/h264_cae/1611052585/mda-maif0tt1rirqp27q.mp4");}));}

https://brucegwo.blog.csdn.net/article/details/136024588

四、小结

flutter开发实战-ijkplayer视频播放器功能

学习记录,每天不停进步。

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

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

相关文章

3D力导向树插件-3d-force-graph学习001

一、引入文件&#xff1a;下载静态js文件引入 1、**以vue项目测试&#xff0c;在index.html文件中引入静态文件&#xff08;js文件可在官网下载&#xff09;** 2、**也曾尝试用npm包下载引入的方法&#xff0c;总是会有报错&#xff0c;所以采用静态js文件引入的方式** 二、基…

【高质量精品】2024美赛B题22页word版高质量半成品论文+多版保奖思路+数据+前四问思路代码等(后续会更新)

一定要点击文末的卡片&#xff0c;进入后&#xff0c;获取完整论文&#xff01;&#xff01; B 题整体模型构建 1. 潜水器动力系统失效&#xff1a;模型需要考虑潜水器在无推进力情况下的行为。 2. 失去与主船通信&#xff1a;考虑无法从主船接收指令或发送位置信息的情况。…

【AIGC核心技术剖析】DreamCraft3D一种层次化的3D内容生成方法

DreamCraft3D是一种用于生成高保真、连贯3D对象的层次化3D内容生成方法。它利用2D参考图像引导几何塑造和纹理增强阶段&#xff0c;通过视角相关扩散模型执行得分蒸馏采样&#xff0c;解决了现有方法中存在的一致性问题。使用Bootstrapped Score Distillation来提高纹理&#x…

LabVIEW与EtherCAT实现风洞安全联锁及状态监测

LabVIEW与EtherCAT实现风洞安全联锁及状态监测 在现代风洞试验中&#xff0c;安全联锁与状态监测系统发挥着至关重要的作用&#xff0c;确保了试验过程的安全性与高效性。介绍了一套基于EtherCAT总线技术和LabVIEW软件开发的风洞安全联锁及状态监测系统。该系统通过实时、可靠…

jmeter-04创建请求

文章目录 一、发送请求-查看响应流程二、新建请求三、选择请求方式&#xff0c;填写url1.发送get请求当只有请求方式不一样的时候&#xff0c;参数都填写在参数栏里面&#xff0c;GET请求与POST请求的区别&#xff1f; 2.发送post请求2.1 application/x-www-form-urlencoded2.2…

基于深度学习的SSVEP分类算法简介

基于深度学习的SSVEP分类算法简介 1、目标与范畴2、深度学习的算法介绍3、参考文献 1、目标与范畴 稳态视觉诱发电位&#xff08;SSVEP&#xff09;是指当受试者持续注视固定频率的闪光或翻转刺激时&#xff0c;在大脑枕-额叶区域诱发的与刺激频率相关的电生理信号。与P300、运…

C系列-柔性数组

&#x1f308;个人主页: 会编程的果子君 ​&#x1f4ab;个人格言:“成为自己未来的主人~” 目录 ​编辑 柔性数组 柔性数组的特点 柔性数组的使用 柔性数组的优势 柔性数组 也许你从来没有听说过柔性数组这个概念&#xff0c;但是它确实是存在的&#xff0c;C99中&#…

PyTorch 2.2 中文官方教程(十八)

开始使用完全分片数据并行&#xff08;FSDP&#xff09; 原文&#xff1a;pytorch.org/tutorials/intermediate/FSDP_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Hamid Shojanazeri&#xff0c;Yanli Zhao&#xff0c;Shen Li 注意…

Hudi学习 6:Hudi使用

准备工作&#xff1a; 1.安装hdfs https://mp.csdn.net/mp_blog/creation/editor/109689143 2.安装spark spark学习4&#xff1a;spark安装_hzp666的博客-CSDN博客 3.安装Scala Hudi学习6&#xff1a;安装和基本操作_hzp666的博客-CSDN博客 spark-shell 写入和读取hudi 2.…

python常用pandas函数nlargest / nsmallest及其手动实现

目录 pandas库 Series和DataFrame nlargest和nsmallest 用法示例 代替方法 手动实现 模拟代码 pandas库 是Python中一个非常强大的数据处理库,提供了高效的数据分析方法和数据结构。它特别适用于处理具有关系型数据或带标签数据的情况,同时在时间序列分析方面也有着出…

基于springboot地方美食分享网站源码和论文

基于springboot地方美食分享网站源码和论文361 首先&#xff0c;论文一开始便是清楚的论述了系统的研究内容。其次&#xff0c;剖析系统需求分析&#xff0c;弄明白“做什么”&#xff0c;分析包括业务分析和业务流程的分析以及用例分析&#xff0c;更进一步明确系统的需求。然…

嵌入式中经典面试题分析

1.关键字static的作用是什么&#xff1f;为什么static变量只初始化一次&#xff1f; 1&#xff09;修饰局部变量&#xff1a;使得变量变成静态变量&#xff0c;存储在静态区&#xff0c;存储在静态区的数据周期和程序相同&#xff0c; 在main函数开始前初始化&#xff0c;在退…

7min到40s:SpringBoot 启动优化实践!

目录 背景 1 耗时问题排查 1.1 观察 SpringBoot 启动 run 方法 1.2 监控 Bean 注入耗时 2 优化方案 2.1 如何解决扫描路径过多&#xff1f; 2.2 如何解决 Bean 初始化高耗时&#xff1f; 3 新的问题 3.1 SpringBoot 自动化装配&#xff0c;让人防不胜防 3.2 使用 sta…

泡泡清新文艺的微社区系统PHP源码

泡泡微社区&#xff0c;小巧而强大&#xff0c;为您带来卓越的社区交流体验。 凭借GoZinc的先进架构&#xff0c;泡泡在保持轻盈身姿的同时&#xff0c;功能一应俱全。前端采用Vue3匠心打造&#xff0c;界面清新简约&#xff0c;三栏式布局仿若Twitter&#xff0c;让您一见倾心…

四、Redis之配置文件

redis配置文件的名称 redis.conf 通过命令 find / -name redis.confvim redis.conf通过 : set nu 设置行号: set nonu 取消行号/关键字 搜索关键字: set noh 取消高亮选择4.1 Units 配置大小单位&#xff0c;开头定义了一些基本的度量单位&#xff0c;只支持 bytes&#…

基于Springboot的校园失物招领网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园失物招领网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

【数据结构】排序---C语言版

七大排序算法 一、对于排序的分类&#xff1a;二、插入排序1、直接插入排序&#xff08;1&#xff09;基本思想&#xff1a;&#xff08;2&#xff09;直接插入排序&#xff1a;&#xff08;3&#xff09;代码实现&#xff1a;&#xff08;4&#xff09;总结&#xff1a; 2、希…

【Django】ORM关系映射

关系映射 在关系型数据库中&#xff0c;通常不会把所有数据都放在同一张表中&#xff0c;不易于扩展&#xff0c;常见的关系映射有&#xff1a; 一对一映射&#xff0c;如一个身份证对应一个人。 一对多映射&#xff0c;如一个班级可以有多个学生。 多对多映射&#xff0c;如…

初始数据库

华子目录 什么是数据库DBMS&#xff08;数据库管理系统&#xff09;数据库系统和文件系统的区别文件系统数据库系统对比区别优缺点总结 常见数据库关系型数据库ACID原则关系型数据库的优缺点优点缺点 非关系型数据库存储方式常见的非关系型数据库非关系型数据库的优缺点优点缺点…

Vivado Tri-MAC IP的例化配置(三速以太网IP)

目录 1 Tri-MAC IP使用RGMII接口的例化配置1.1 Data Rate1.2 interface配置1.3 Shared Logic配置1.4 Features 2 配置完成IP例化视图 1 Tri-MAC IP使用RGMII接口的例化配置 在网络设计中&#xff0c;使用的IP核一般为三速以太网IP核&#xff0c;使用时在大多数场景下为配置为三…