继续看雷霄骅的 课程资料 - 基于FFmpeg+SDL的视频播放器的制作

一、SDL 简介

参看:WIKI -- Simple DirectMedia Layer

参看:最简单的视音频播放示例9:SDL2播放PCM

参看:SDL介绍

SDL (Simple DirectMedia Layer)是一套开源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS等)的应用软件。目前 SDL 多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。用下面这张图可以很明确地说明 SDL 的用途。

SDL 分为几个子系统:

Basics(基本)
    初始化和关闭,配置变量,错误处理,日志处理
vedio(视频)
    显示和窗口管理,表面功能,渲染加速等
Input Events (输入事件)
    事件处理,支持键盘,鼠标,操纵杆和游戏控制器
Force Feedback (力反馈)
    SDL_haptic.h支持“强制反馈”
Audio(音频)
    SDL_audio.h实现音频设备管理,播放和录制
Threads(主题)
    多线程:线程管理,线程同步原语,原子操作
Timers (计时器)
    定时器支持
File Abstraction (文件抽象)
    文件系统路径,文件I / O抽象
Shared Object Support (共享对象支持)
    共享对象加载和功能查找
Platform and CPU Information (平台和CPU信息)
    平台检测,CPU特征检测,字节顺序和字节交换,位操作
Power Mangement (能源管理)
    电源管理状态
Additional (额外)
    平台特定的功能

除了这个基本的低级支持之外,还有几个独立的官方图书馆提供了更多的功能。 这些包括“标准库”,并在官方网站上提供,并包含在官方文件中:
SDL_image - 支持多种图像格式[19]
SDL_mixer - 复合音频功能,主要用于混音[20]
SDL_net - 网络支持[21]
SDL_ttf - TrueType字体渲染支持[22]
SDL_rtf - 简单的富文本格式渲染[23]

二、VS 下 SDL 开发环境的搭建

这是第三遍了啊。。

新建控制台工程

打开 VS;
文件->新建->项目->Win32控制台应用程序,点击完成。
注意,选择的位置最好不要有 空格或者汉字。

拷贝 SDL 开发文件

头文件( *.h)拷贝至项目文件夹的include子文件夹下
导入库文件( *.lib)拷贝至项目文件夹的lib子文件夹下
动态库文件( *.dll) 拷贝至项目文件夹下
点击右键,选择在资源管理器中打开文件夹,进入项目目录。
(注意,如果手动进入注意文件夹位置,我就是没找好位置,试了半天最后才发现,将上面的这些文件拷贝到错误的文件夹下了)

配置开发文件

打开属性面板

解决方案资源管理器->右键单击项目->属性

头文件配置

配置属性->C/C++->常规->附加包含目录,输入“ include”(刚才拷贝头文件的目录)

导入库配置

配置属性->链接器->常规->附加库目录,输入“ lib” (刚才拷贝库文件的目录)

配置属性->链接器->输入->附加依赖项,输入“ SDL2.lib;SDL2main.lib”(导入库的文件名)

动态库不用配置

测试

将 SDL.cpp 添加测试代码,改为如下:
// SDL.cpp : 定义控制台应用程序的入口点。
//
#include <stdio.h>
#include "stdafx.h"
extern "C"
{
#include "SDL2/SDL.h"
}int main()
{if (SDL_Init(SDL_INIT_VIDEO)) {printf("Could not initialize SDL - %s\n", SDL_GetError());}else {printf("Success init SDL");}return 0;
}
打断点,如果不打断点,调试的时候一闪而过什么也看不到的。
在return 0; 左边点击一下,出现红点,即为断点。
然后点击本地Windows调试器,出现此项目已经过期,选择 是。
可看到出现结果,说明 SDL 配置成功。

这里我用提供的 lib 文件,遇到如下问题
1>------ 已启动生成: 项目: SDL, 配置: Debug Win32 ------
1>stdafx.cpp
1>SDL.cpp
1>MSVCRTD.lib(initializers.obj) : warning LNK4098: 默认库“msvcrt.lib”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: 无法解析的外部符号 __imp__fprintf,该符号在函数 _ShowError 中被引用
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: 无法解析的外部符号 __imp____iob_func,该符号在函数 _ShowError 中被引用
1>D:\zslfchenjuke\work2017\SDL\SDL\Debug\SDL.exe : fatal error LNK1120: 2 个无法解析的外部命令
1>已完成生成项目“SDL.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

问题分析:因为我用的是 VS2017,而提供的lib实在 VS 2013上执行的。

下载最新的 SDL 扩展库。
下载:Index of /sdl-builds/sdl-visualstudio
下载:SDL-devel-1.2.15-VC.zip (Visual C++)
扩展:Installing SDL
扩展:Introduction to SDL 2.0

三、SDL视频显示的函数

SDL视频显示函数简介

SDL_Init():初始化SDL系统
SDL_CreateWindow():创建窗口SDL_Window
SDL_CreateRenderer():创建渲染器SDL_Renderer
SDL_CreateTexture():创建纹理SDL_Texture
SDL_UpdateTexture():设置纹理的数据
SDL_RenderCopy():将纹理的数据拷贝给渲染器
SDL_RenderPresent():显示
SDL_Delay():工具函数,用于延时。
SDL_Quit():退出SDL系统

SDL视频显示的流程图如下所示

SDL源代码分析系列文章列表:

SDL2源代码分析1:初始化(SDL_Init())

SDL2源代码分析2:窗口(SDL_Window)

SDL2源代码分析3:渲染器(SDL_Renderer)

SDL2源代码分析4:纹理(SDL_Texture)

SDL2源代码分析5:更新纹理(SDL_UpdateTexture())

SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())

SDL2源代码分析7:显示(SDL_RenderPresent())

SDL2源代码分析8:视频显示总结

四、SDL视频显示的数据结构

SDL视频显示的数据结构如下所示

SDL数据结构简介

SDL_Window   代表了一个“窗口”
SDL_Renderer  代表了一个“渲染器”
SDL_Texture     代表了一个“纹理”
SDL_Rect          一个简单的矩形结构

五、示例解析

使用 SDL 播放 yuv 文件

#include <stdio.h>
#include "stdafx.h"
extern "C"
{
#include "SDL2/SDL.h"
}const int bpp = 12;
//screan 为屏幕长宽,pixel为视频长宽
int screen_w = 640, screen_h = 272;
const int pixel_w = 640, pixel_h = 272;unsigned char buffer[pixel_w*pixel_h*bpp / 8];//Refresh Event
#define REFRESH_EVENT  (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT  (SDL_USEREVENT + 2)int thread_exit = 0;int refresh_video(void *opaque) {thread_exit = 0;while (thread_exit == 0) {SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event);  //发送一个事件SDL_Delay(40);  //工具函数,可用于调节播放速度}thread_exit = 0;//BreakSDL_Event event;event.type = BREAK_EVENT;SDL_PushEvent(&event);return 0;
}int main(int argc, char* argv[])
{//初始化 SDL 系统if (SDL_Init(SDL_INIT_VIDEO)) {printf("Could not initialize SDL - %s\n", SDL_GetError());return -1;}SDL_Window *screen;//SDL 2.0 Support for multiple windows//创建窗口 SDL_Windowscreen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!screen) {printf("SDL: could not create window - exiting:%s\n", SDL_GetError());return -1;}//创建渲染器SDL_RendererSDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);Uint32 pixformat = 0;//IYUV: Y + U + V  (3 planes)//YV12: Y + V + U  (3 planes)pixformat = SDL_PIXELFORMAT_IYUV;//创建纹理 SDL_TextureSDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);FILE *fp = NULL;//打开yuv文件fp = fopen("output.yuv", "rb+");if (fp == NULL) {printf("cannot open this file\n");return -1;}//SDL_Rect srcRect[4];//SDL_Rect sdlRect[4];SDL_Rect sdlRect;//创建一个线程SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video, NULL, NULL);SDL_Event event;while (1) {//等待一个事件SDL_WaitEvent(&event);if (event.type == REFRESH_EVENT) {if (fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp) != pixel_w*pixel_h*bpp / 8) {// Loopfseek(fp, 0, SEEK_SET);fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp);}//设置纹理的数据SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);
#if 0 //分屏播放srcRect[0].x =0;srcRect[0].y = 0;srcRect[0].w = 320;srcRect[0].h = 176;srcRect[1].x =320;srcRect[1].y = 0;srcRect[1].w = 320;srcRect[1].h = 176;srcRect[2].x =0;srcRect[2].y = 176;srcRect[2].w = 320;srcRect[2].h = 176;srcRect[3].x =320;srcRect[3].y = 176;srcRect[3].w = 320;srcRect[3].h = 176;//FIX: If window is resizesdlRect[0].x = 0;sdlRect[0].y = 0;sdlRect[0].w = 320;sdlRect[0].h = 176;sdlRect[1].x = 330;sdlRect[1].y = 0;sdlRect[1].w = 320;sdlRect[1].h = 176;sdlRect[2].x = 0;sdlRect[2].y = 186;sdlRect[2].w = 320;sdlRect[2].h = 176;sdlRect[3].x = 330;sdlRect[3].y = 186;sdlRect[3].w = 320;sdlRect[3].h = 176;//清空纹理SDL_RenderClear( sdlRenderer );//将纹理的数据拷贝给渲染器SDL_RenderCopy( sdlRenderer, sdlTexture,/*NULL*/ &srcRect[0], &sdlRect[0]);SDL_RenderCopy(sdlRenderer, sdlTexture,/*NULL*/ &srcRect[1], &sdlRect[1]);SDL_RenderCopy(sdlRenderer, sdlTexture,/*NULL*/ &srcRect[2], &sdlRect[2]);SDL_RenderCopy(sdlRenderer, sdlTexture,/*NULL*/ &srcRect[3], &sdlRect[3]);
#endifsdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;SDL_RenderClear(sdlRenderer);SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);//显示SDL_RenderPresent(sdlRenderer);}else if (event.type == SDL_WINDOWEVENT) {//If ResizeSDL_GetWindowSize(screen, &screen_w, &screen_h);}else if (event.type == SDL_QUIT) {thread_exit = 1;}else if (event.type == BREAK_EVENT) {break;}}//退出 SDL 系统SDL_Quit();return 0;
}

演示结果:

窗口可移动、可调整大小。

项目下载:

下载:SDL 项目工程

六、示例解析

拷贝FFmpeg的开发文件(lib、include、dll文件),配置VS2017这个我就不再多说了。

利用 FFmpeg 把MP4解码为YUV,然后在 SDL 上播放。

/**
* 最简单的基于FFmpeg的视频播放器2(SDL升级版)
* Simplest FFmpeg Player 2(SDL Update)
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 第2版使用SDL2.0取代了第一版中的SDL1.2
* Version 2 use SDL 2.0 instead of SDL 1.2 in version 1.
*
* 本程序实现了视频文件的解码和显示(支持HEVC,H.264,MPEG2等)。
* 是最简单的FFmpeg视频解码方面的教程。
* 通过学习本例子可以了解FFmpeg的解码流程。
* 本版本中使用SDL消息机制刷新视频画面。
* This software is a simplest video player based on FFmpeg.
* Suitable for beginner of FFmpeg.
*
* 备注:
* 标准版在播放视频的时候,画面显示使用延时40ms的方式。这么做有两个后果:
* (1)SDL弹出的窗口无法移动,一直显示是忙碌状态
* (2)画面显示并不是严格的40ms一帧,因为还没有考虑解码的时间。
* SU(SDL Update)版在视频解码的过程中,不再使用延时40ms的方式,而是创建了
* 一个线程,每隔40ms发送一个自定义的消息,告知主函数进行解码显示。这样做之后:
* (1)SDL弹出的窗口可以移动了
* (2)画面显示是严格的40ms一帧
* Remark:
* Standard Version use's SDL_Delay() to control video's frame rate, it has 2
* disadvantages:
* (1)SDL's Screen can't be moved and always "Busy".
* (2)Frame rate can't be accurate because it doesn't consider the time consumed
* by avcodec_decode_video2()
* SU(SDL Update)Version solved 2 problems above. It create a thread to send SDL
* Event every 40ms to tell the main loop to decode and show video frames.
*/#include <stdio.h>
#include "stdafx.h"
#define __STDC_CONSTANT_MACROS#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "SDL2/SDL.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
};
#endif
#endif//Refresh Event
#define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)#define SFM_BREAK_EVENT  (SDL_USEREVENT + 2)int thread_exit = 0;
int thread_pause = 0;int sfp_refresh_thread(void *opaque) {thread_exit = 0;thread_pause = 0;while (!thread_exit) {if (!thread_pause) {SDL_Event event;event.type = SFM_REFRESH_EVENT;SDL_PushEvent(&event); //发送一个事件}SDL_Delay(40); //可用于调节播放速度}thread_exit = 0;thread_pause = 0;//BreakSDL_Event event;event.type = SFM_BREAK_EVENT;SDL_PushEvent(&event);return 0;
}int main(int argc, char* argv[])
{AVFormatContext    *pFormatCtx;int             i, videoindex;AVCodecContext    *pCodecCtx;AVCodec          *pCodec;AVFrame *pFrame, *pFrameYUV;uint8_t *out_buffer;AVPacket *packet;int ret, got_picture;//------------SDL----------------int screen_w, screen_h;SDL_Window *screen;SDL_Renderer* sdlRenderer;SDL_Texture* sdlTexture;SDL_Rect sdlRect;SDL_Thread *video_tid;SDL_Event event;struct SwsContext *img_convert_ctx;//输入文件路径char filepath[] = "Tai.mp4";av_register_all(); //注册所有组件avformat_network_init(); //初始化网络pFormatCtx = avformat_alloc_context(); //初始化一个 AVFormatContext if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) { //打开输入的视频文件printf("Couldn't open input stream.\n");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL)<0) { //获取视频文件信息printf("Couldn't find stream information.\n");return -1;}videoindex = -1;for (i = 0; i<pFormatCtx->nb_streams; i++)if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}if (videoindex == -1) {printf("Didn't find a video stream.\n");return -1;}pCodecCtx = pFormatCtx->streams[videoindex]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id); //查找解码器if (pCodec == NULL) {printf("Codec not found.\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) { //打开解码器printf("Could not open codec.\n");return -1;}pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);packet = (AVPacket *)av_malloc(sizeof(AVPacket));//Output Info-----------------------------printf("---------------- File Information ---------------\n");av_dump_format(pFormatCtx, 0, filepath, 0);printf("-------------------------------------------------\n");img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);//初始化 SDL 系统if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {printf("Could not initialize SDL - %s\n", SDL_GetError());return -1;}//SDL 2.0 Support for multiple windowsscreen_w = pCodecCtx->width;screen_h = pCodecCtx->height;//创建窗口screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!screen) {printf("SDL: could not create window - exiting:%s\n", SDL_GetError());return -1;}//创建渲染器sdlRenderer = SDL_CreateRenderer(screen, -1, 0);//IYUV: Y + U + V  (3 planes)//YV12: Y + V + U  (3 planes)//创建纹理sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, screen_w, screen_h);//创建一个线程video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);//------------SDL End------------//Event Loopfor (;;) {//WaitSDL_WaitEvent(&event);if (event.type == SFM_REFRESH_EVENT) {//------------------------------ if (av_read_frame(pFormatCtx, packet) >= 0) { //读取一帧压缩数据if (packet->stream_index == videoindex) {ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); //解码一帧压缩数据if (ret < 0) {printf("Decode Error.\n");return -1;}if (got_picture) {sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);//SDL---------------------------//设置纹理的数据SDL_UpdateTexture(sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]);sdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;//清空纹理SDL_RenderClear(sdlRenderer);//SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect );  //将纹理的数据拷贝给渲染器SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);//显示SDL_RenderPresent(sdlRenderer);//SDL End-----------------------}}av_free_packet(packet);}else {//Exit Threadthread_exit = 1;}}else if (event.type == SDL_WINDOWEVENT) {//If Resize  SDL_GetWindowSize(screen, &screen_w, &screen_h);}else if (event.type == SDL_KEYDOWN) {//Pauseif (event.key.keysym.sym == SDLK_SPACE)thread_pause = !thread_pause;}else if (event.type == SDL_QUIT) {thread_exit = 1;}else if (event.type == SFM_BREAK_EVENT) {break;}}sws_freeContext(img_convert_ctx);SDL_Quit();//--------------av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;
}

示例总结

结合上一篇文章的 ffmpeg再学习 -- FFmpeg解码知识 将视频转 yuv ,然后使用 SDL 播放。

这里遇到了两个问题。
第一,无法解析的外部符号。
1>------ 已启动生成: 项目: SDL, 配置: Debug Win32 ------
1>SDL.obj : error LNK2019: 无法解析的外部符号 _av_malloc,该符号在函数 _SDL_main 中被引用
1>SDL.obj : error LNK2019: 无法解析的外部符号 _av_frame_alloc,该符号在函数 _SDL_main 中被引用
1>SDL.obj : error LNK2019: 无法解析的外部符号 _av_frame_free,该符号在函数 _SDL_main 中被引用
1>SDL.obj : error LNK2019: 无法解析的外部符号 _avcodec_open2,该符号在函数 _SDL_main 中被引用

原因是未将FFmpeg 的 dll文件,拷贝到相应的位置。

解决方法:点击项目->属性->配置属性->链接器->输入->附加依赖项(添加。。)
第二,原项目示例,无法调整窗口大小。
原因是创建窗口时,未添加 SDL_WINDOW_RESIZABLE
//创建窗口screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

项目下载:

下载:SDL 播放MP4视频 项目工程

七、脱离开发环境的独立播放器

动态链接库不能被编译进应用程序。因而使用应用程序的时候必须在相同目录下保存用到的动态链接库文件。
如上图,点击 SDL.exe 即可直接播放视频。

八、播放任意视频

注意到上例中只能播放指定的一个视频,
    //输入文件路径char filepath[] = "Tai.mp4";
那么播放任意视频该如何操作?
利用 main 函数参数,参看:C语言再学习 -- 函数
argc argv:全称为ARGument Counter 和 ARGument Vector。其中argv存储了来自于命令行的参数;而argc存储了参数的个数。
例如,在命令行中输入“ ffmpeg -i test.mkv test.ts ”,则argc取值为4,而argv[]数组取值如下:
argv[0]="ffmpeg"
argv[1]="-i"
argv[2]="test.mkv"
argv[3]="test.ts"
只需如下更改,即可播放任意视频。
char *filepath = argv[1];
然后,利用 cmd 命令窗口打开 SDL.exe 
快捷键为 按住 shift + 右键,选择 在此处打开命令窗口(W) 
然后输入:SDL.exe 视频名称  即可播放任意视频

FFmpeg再学习 -- SDL 环境搭建和视频显示相关推荐

  1. FFmpeg再学习 -- FFmpeg解码知识

    继续看雷霄骅的 课程资料 - 基于FFmpeg+SDL的视频播放器的制作 前面用了五个篇幅来讲 FFmpeg,其主要目的是为实现将图片转视频的功能. 总的来说,对于 FFmepg 多少有一些了解了.但 ...

  2. visual studio学习python_python3从零学习-开发环境搭建之Visual Studio Code篇

    开发环境搭建之Visual Studio Code篇 上一节讲了Python环境的安装和开发环境的安装,本节再重点讲下Visual Studio Code的配置.安装 请看我上一篇文章<pyth ...

  3. FFmpeg再学习 -- 硬件加速编解码

    为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...

  4. donet 微服务开发 学习-Docker环境搭建 win7 docker 环境配置

    donet 微服务开发 学习-Docker环境搭建 win7 docker 环境配置 目的介绍 下载安装 安装 Docker Quickstart Terminal 目的介绍 donet 微服务开发 ...

  5. ubuntu深度学习软硬件开发环境搭建

    硬件 先从硬件自已配机器开始: 目前对于个人来说,性价比比较高的深度学习显卡是那个11G显存的GTX 1080Ti.这里显卡定了,接下来就是主板内存硬盘,显示器.先报一下我配的机器配置: CPU 英特 ...

  6. 【Linux Mint 深度学习开发环境搭建】开发软件安装

    系列文章目录 第一章 Linux mint 深度学习开发环境搭建之Nvidia显卡相关软件安装 第二章 Linux mint 深度学习开发环境搭建之开发软件安装 第三章 Linux mint 深度学习 ...

  7. 深度学习工作站环境搭建 ubantu16.04 安装显卡驱动 CUDA8.0 cuDNN6 anaconda tensorflow1.4.0 opencv3.4 含泪总结

    深度学习工作站环境搭建 ubantu16.04 安装显卡驱动 CUDA8.0 cuDNN6 anaconda tensorflow opencv 1 安装ubantu16.04 安装时不要在线更新,在 ...

  8. IOS开发学习 IDE环境搭建教程

    IOS开发学习 IDE环境搭建教程是本文要介绍的内容,在坛子里逛了一圈,发现一篇好的文章,与友们分享一下,要有耐心的看整个过程,不多说,直接进入话题. 安装条件: 硬件:一台拥有支持虚拟技术的64位双 ...

  9. hbase_学习_01_HBase环境搭建(单机)

    一.前言 本文承接上一篇:hadoop_学习_02_Hadoop环境搭建(单机)  ,主要是搭建HBase的单机环境 二.环境准备 1.说明 hbase 的下载来源有: 官方版本:http://arc ...

最新文章

  1. Web应用渗透测试框架Arachni
  2. Android系统源代码下载
  3. 怎么实现两周联动加减速_行车记录仪种类繁多不知道怎么选?学会这几招,简单又有效...
  4. 吴恩达机器学习作业Python实现(四):神经网络(反向传播)
  5. class 原生js获取父元素_JS获取节点的兄弟,父级,子级元素的方法
  6. 【Bootstrap】 typeahead自动补全
  7. 昂达v819i安装win8.1时报错
  8. bom_clear.php,金蝶KIS专业版常用SQL语句
  9. android友盟错误统计,Android—友盟统计收集错误和在线统计
  10. 士兵 POJ1723
  11. canva五角星空html,使用canvas绘制一个五角星
  12. 申请公司苹果开发者账号-2020最新
  13. iOS性能优化之耗电量
  14. Lenovo windows 解决win键失灵
  15. 射频百科:双工器是什么?双工器工作原理
  16. 地图采集车的那些事 | 惯性导航
  17. 大数据学习路线,如何学习大数据?
  18. atca背板_高速背板及相关标准介绍
  19. Scratch2Cards来自官网
  20. 基于.net6.0在wpf桌面应用中发布webApi服务示例

热门文章

  1. Appium——appium之mac环境安装
  2. ABAP 7.53 中的ABAP SQL(原Open SQL)新特性
  3. jquery实现滚动条滚动到一定高度导航固定不变
  4. JQuery-Table斑马线
  5. spring连数据库的配置文件(applicationContext.xml)
  6. asp.net mvc自动完成
  7. 最小二乘算法MATLAB代码实现
  8. createrepo常用参数
  9. Android中的音乐播放
  10. php html采集,php file_get_contents函数轻松采集html数据