[转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

时间:2023-01-25 00:13:00

=====================================================
最简单的基于FFmpeg的AVDevice例子文章列表:

最简单的基于FFmpeg的AVDevice例子(读取摄像头)

最简单的基于FFmpeg的AVDevice例子(屏幕录制)
=====================================================

FFmpeg中有一个和多媒体设备交互的类库:Libavdevice。使用这个库可以读取电脑(或者其他设备上)的多媒体设备的数据,或者输出数据到指定的多媒体设备上。

Libavdevice支持以下设备作为输入端:

alsa
avfoundation
bktr
dshow
dv1394
fbdev
gdigrab
iec61883
jack
lavfi
libcdio
libdc1394
openal
oss
pulse
qtkit
sndio
video4linux2, v4l2
vfwcap
x11grab
decklink

Libavdevice支持以下设备作为输出端:

alsa
caca
decklink
fbdev
opengl
oss
pulse
sdl
sndio
xv

libavdevice使用

计划记录两个基于FFmpeg的libavdevice类库的例子,分成两篇文章写。本文记录一个基于FFmpeg的Libavdevice类库读取摄像头数据的例子。下一篇文章记录一个基于FFmpeg的Libavdevice类库录制屏幕的例子。本文程序读取计算机上的摄像头的数据并且解码显示出来。有关解码显示方面的代码本文不再详述,可以参考文章:
100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)

本文主要记录使用libavdevice需要注意的步骤。

首先,使用libavdevice的时候需要包含其头文件:

  1. #include "libavdevice/avdevice.h"

然后,在程序中需要注册libavdevice:

  1. avdevice_register_all();

接下来就可以使用libavdevice的功能了。
使用libavdevice读取数据和直接打开视频文件比较类似。因为系统的设备也被FFmpeg认为是一种输入的格式(即AVInputFormat)。使用FFmpeg打开一个普通的视频文件使用如下函数:

  1. AVFormatContext *pFormatCtx = avformat_alloc_context();
  2. avformat_open_input(&pFormatCtx, "test.h265",NULL,NULL);

使用libavdevice的时候,唯一的不同在于需要首先查找用于输入的设备。在这里使用av_find_input_format()完成:

  1. AVFormatContext *pFormatCtx = avformat_alloc_context();
  2. AVInputFormat *ifmt=av_find_input_format("vfwcap");
  3. avformat_open_input(&pFormatCtx, 0, ifmt,NULL);

上述代码首先指定了vfw设备作为输入设备,然后在URL中指定打开第0个设备(在我自己计算机上即是摄像头设备)。
在Windows平台上除了使用vfw设备作为输入设备之外,还可以使用DirectShow作为输入设备:

  1. AVFormatContext *pFormatCtx = avformat_alloc_context();
  2. AVInputFormat *ifmt=av_find_input_format("dshow");
  3. avformat_open_input(&pFormatCtx,"video=Integrated Camera",ifmt,NULL) ;

使用ffmpeg.exe打开vfw设备和Directshow设备的方法可以参考文章:
FFmpeg获取DirectShow设备数据(摄像头,录屏)

注意事项

1. URL的格式是"video={设备名称}",但是设备名称外面不能加引号。例如在上述例子中URL是"video=Integrated Camera",而不能写成"video=\"Integrated Camera\"",否则就无法打开设备。这与直接使用ffmpeg.exe打开dshow设备(命令为:ffmpeg -list_options true -f dshow -i video="Integrated Camera")有很大的不同。
2. Dshow的设备名称必须要提前获取,在这里有两种方法:

(1) 通过FFmpeg编程实现。使用如下代码:

  1. //Show Device
  2. void show_dshow_device(){
  3. AVFormatContext *pFormatCtx = avformat_alloc_context();
  4. AVDictionary* options = NULL;
  5. av_dict_set(&options,"list_devices","true",0);
  6. AVInputFormat *iformat = av_find_input_format("dshow");
  7. printf("Device Info=============\n");
  8. avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
  9. printf("========================\n");
  10. }

上述代码实际上相当于输入了下面一条命令:

  1. ffmpeg -list_devices true -f dshow -i dummy

执行的结果如下图所示:

[转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

该方法好处是可以使用程序自动获取名称。但是当设备名称中包含中文字符的时候,会出现设备名称为乱码的情况。如果直接把乱码的设备名作为输入的话,是无法打开该设备的。这时候需要把乱码ANSI转换为UTF-8。例如上图中的第一个音频设备显示为“鍐呰楹﹀厠椋?(Conexant 20672 SmartAudi”,转码之后即为“内装麦克风 (Conexant 20672 SmartAudi”。使用转码之后的名称即可打开该设备。

(2) 自己去系统中看。
这个方法更简单一些,但是缺点是需要手工操作。该方法使用DirectShow的调试工具GraphEdit(或者网上下一个GraphStudioNext)即可查看输入名称。
打开GraphEdit选择“图像->插入滤镜”

 [转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

然后就可以通过查看Audio Capture Sources来查看音频输入设备的简体中文名称了。从图中可以看出是“内装麦克风 (Conexant 20672 SmartAudi”。

 [转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

在Linux平台上可以使用video4linux2打开视频设备;在MacOS上,可以使用avfoundation打开视频设备,这里不再详述。

代码

下面直接贴上程序代码:

  1. /**
  2. * 最简单的基于FFmpeg的AVDevice例子(读取摄像头)
  3. * Simplest FFmpeg Device (Read Camera)
  4. *
  5. * 雷霄骅 Lei Xiaohua
  6. * leixiaohua1020@126.com
  7. * 中国传媒大学/数字电视技术
  8. * Communication University of China / Digital TV Technology
  9. * http://blog.csdn.net/leixiaohua1020
  10. *
  11. * 本程序实现了本地摄像头数据的获取解码和显示。是基于FFmpeg
  12. * 的libavdevice类库最简单的例子。通过该例子,可以学习FFmpeg中
  13. * libavdevice类库的使用方法。
  14. * 本程序在Windows下可以使用2种方式读取摄像头数据:
  15. *  1.VFW: Video for Windows 屏幕捕捉设备。注意输入URL是设备的序号,
  16. *          从0至9。
  17. *  2.dshow: 使用Directshow。注意作者机器上的摄像头设备名称是
  18. *         “Integrated Camera”,使用的时候需要改成自己电脑上摄像头设
  19. *          备的名称。
  20. * 在Linux下可以使用video4linux2读取摄像头设备。
  21. * 在MacOS下可以使用avfoundation读取摄像头设备。
  22. *
  23. * This software read data from Computer's Camera and play it.
  24. * It's the simplest example about usage of FFmpeg's libavdevice Library.
  25. * It's suiltable for the beginner of FFmpeg.
  26. * This software support 2 methods to read camera in Microsoft Windows:
  27. *  1.gdigrab: VfW (Video for Windows) capture input device.
  28. *             The filename passed as input is the capture driver number,
  29. *             ranging from 0 to 9.
  30. *  2.dshow: Use Directshow. Camera's name in author's computer is
  31. *             "Integrated Camera".
  32. * It use video4linux2 to read Camera in Linux.
  33. * It use avfoundation to read Camera in MacOS.
  34. *
  35. */
  36. #include <stdio.h>
  37. #define __STDC_CONSTANT_MACROS
  38. #ifdef _WIN32
  39. //Windows
  40. extern "C"
  41. {
  42. #include "libavcodec/avcodec.h"
  43. #include "libavformat/avformat.h"
  44. #include "libswscale/swscale.h"
  45. #include "libavdevice/avdevice.h"
  46. #include "SDL/SDL.h"
  47. };
  48. #else
  49. //Linux...
  50. #ifdef __cplusplus
  51. extern "C"
  52. {
  53. #endif
  54. #include <libavcodec/avcodec.h>
  55. #include <libavformat/avformat.h>
  56. #include <libswscale/swscale.h>
  57. #include <libavdevice/avdevice.h>
  58. #include <SDL/SDL.h>
  59. #ifdef __cplusplus
  60. };
  61. #endif
  62. #endif
  63. //Output YUV420P
  64. #define OUTPUT_YUV420P 0
  65. //'1' Use Dshow
  66. //'0' Use VFW
  67. #define USE_DSHOW 0
  68. //Refresh Event
  69. #define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)
  70. #define SFM_BREAK_EVENT  (SDL_USEREVENT + 2)
  71. int thread_exit=0;
  72. int sfp_refresh_thread(void *opaque)
  73. {
  74. thread_exit=0;
  75. while (!thread_exit) {
  76. SDL_Event event;
  77. event.type = SFM_REFRESH_EVENT;
  78. SDL_PushEvent(&event);
  79. SDL_Delay(40);
  80. }
  81. thread_exit=0;
  82. //Break
  83. SDL_Event event;
  84. event.type = SFM_BREAK_EVENT;
  85. SDL_PushEvent(&event);
  86. return 0;
  87. }
  88. //Show Dshow Device
  89. void show_dshow_device(){
  90. AVFormatContext *pFormatCtx = avformat_alloc_context();
  91. AVDictionary* options = NULL;
  92. av_dict_set(&options,"list_devices","true",0);
  93. AVInputFormat *iformat = av_find_input_format("dshow");
  94. printf("========Device Info=============\n");
  95. avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
  96. printf("================================\n");
  97. }
  98. //Show Dshow Device Option
  99. void show_dshow_device_option(){
  100. AVFormatContext *pFormatCtx = avformat_alloc_context();
  101. AVDictionary* options = NULL;
  102. av_dict_set(&options,"list_options","true",0);
  103. AVInputFormat *iformat = av_find_input_format("dshow");
  104. printf("========Device Option Info======\n");
  105. avformat_open_input(&pFormatCtx,"video=Integrated Camera",iformat,&options);
  106. printf("================================\n");
  107. }
  108. //Show VFW Device
  109. void show_vfw_device(){
  110. AVFormatContext *pFormatCtx = avformat_alloc_context();
  111. AVInputFormat *iformat = av_find_input_format("vfwcap");
  112. printf("========VFW Device Info======\n");
  113. avformat_open_input(&pFormatCtx,"list",iformat,NULL);
  114. printf("=============================\n");
  115. }
  116. //Show AVFoundation Device
  117. void show_avfoundation_device(){
  118. AVFormatContext *pFormatCtx = avformat_alloc_context();
  119. AVDictionary* options = NULL;
  120. av_dict_set(&options,"list_devices","true",0);
  121. AVInputFormat *iformat = av_find_input_format("avfoundation");
  122. printf("==AVFoundation Device Info===\n");
  123. avformat_open_input(&pFormatCtx,"",iformat,&options);
  124. printf("=============================\n");
  125. }
  126. int main(int argc, char* argv[])
  127. {
  128. AVFormatContext *pFormatCtx;
  129. int             i, videoindex;
  130. AVCodecContext  *pCodecCtx;
  131. AVCodec         *pCodec;
  132. av_register_all();
  133. avformat_network_init();
  134. pFormatCtx = avformat_alloc_context();
  135. //Open File
  136. //char filepath[]="src01_480x272_22.h265";
  137. //avformat_open_input(&pFormatCtx,filepath,NULL,NULL)
  138. //Register Device
  139. avdevice_register_all();
  140. //Windows
  141. #ifdef _WIN32
  142. //Show Dshow Device
  143. show_dshow_device();
  144. //Show Device Options
  145. show_dshow_device_option();
  146. //Show VFW Options
  147. show_vfw_device();
  148. #if USE_DSHOW
  149. AVInputFormat *ifmt=av_find_input_format("dshow");
  150. //Set own video device's name
  151. if(avformat_open_input(&pFormatCtx,"video=Integrated Camera",ifmt,NULL)!=0){
  152. printf("Couldn't open input stream.\n");
  153. return -1;
  154. }
  155. #else
  156. AVInputFormat *ifmt=av_find_input_format("vfwcap");
  157. if(avformat_open_input(&pFormatCtx,"0",ifmt,NULL)!=0){
  158. printf("Couldn't open input stream.\n");
  159. return -1;
  160. }
  161. #endif
  162. #elif defined linux
  163. //Linux
  164. AVInputFormat *ifmt=av_find_input_format("video4linux2");
  165. if(avformat_open_input(&pFormatCtx,"/dev/video0",ifmt,NULL)!=0){
  166. printf("Couldn't open input stream.\n");
  167. return -1;
  168. }
  169. #else
  170. show_avfoundation_device();
  171. //Mac
  172. AVInputFormat *ifmt=av_find_input_format("avfoundation");
  173. //Avfoundation
  174. //[video]:[audio]
  175. if(avformat_open_input(&pFormatCtx,"0",ifmt,NULL)!=0){
  176. printf("Couldn't open input stream.\n");
  177. return -1;
  178. }
  179. #endif
  180. if(avformat_find_stream_info(pFormatCtx,NULL)<0)
  181. {
  182. printf("Couldn't find stream information.\n");
  183. return -1;
  184. }
  185. videoindex=-1;
  186. for(i=0; i<pFormatCtx->nb_streams; i++)
  187. if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
  188. {
  189. videoindex=i;
  190. break;
  191. }
  192. if(videoindex==-1)
  193. {
  194. printf("Couldn't find a video stream.\n");
  195. return -1;
  196. }
  197. pCodecCtx=pFormatCtx->streams[videoindex]->codec;
  198. pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  199. if(pCodec==NULL)
  200. {
  201. printf("Codec not found.\n");
  202. return -1;
  203. }
  204. if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
  205. {
  206. printf("Could not open codec.\n");
  207. return -1;
  208. }
  209. AVFrame *pFrame,*pFrameYUV;
  210. pFrame=av_frame_alloc();
  211. pFrameYUV=av_frame_alloc();
  212. //unsigned char *out_buffer=(unsigned char *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
  213. //avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
  214. //SDL----------------------------
  215. if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
  216. printf( "Could not initialize SDL - %s\n", SDL_GetError());
  217. return -1;
  218. }
  219. int screen_w=0,screen_h=0;
  220. SDL_Surface *screen;
  221. screen_w = pCodecCtx->width;
  222. screen_h = pCodecCtx->height;
  223. screen = SDL_SetVideoMode(screen_w, screen_h, 0,0);
  224. if(!screen) {
  225. printf("SDL: could not set video mode - exiting:%s\n",SDL_GetError());
  226. return -1;
  227. }
  228. SDL_Overlay *bmp;
  229. bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen);
  230. SDL_Rect rect;
  231. rect.x = 0;
  232. rect.y = 0;
  233. rect.w = screen_w;
  234. rect.h = screen_h;
  235. //SDL End------------------------
  236. int ret, got_picture;
  237. AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
  238. #if OUTPUT_YUV420P
  239. FILE *fp_yuv=fopen("output.yuv","wb+");
  240. #endif
  241. struct SwsContext *img_convert_ctx;
  242. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  243. //------------------------------
  244. SDL_Thread *video_tid = SDL_CreateThread(sfp_refresh_thread,NULL);
  245. //
  246. SDL_WM_SetCaption("Simplest FFmpeg Read Camera",NULL);
  247. //Event Loop
  248. SDL_Event event;
  249. for (;;) {
  250. //Wait
  251. SDL_WaitEvent(&event);
  252. if(event.type==SFM_REFRESH_EVENT){
  253. //------------------------------
  254. if(av_read_frame(pFormatCtx, packet)>=0){
  255. if(packet->stream_index==videoindex){
  256. ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
  257. if(ret < 0){
  258. printf("Decode Error.\n");
  259. return -1;
  260. }
  261. if(got_picture){
  262. SDL_LockYUVOverlay(bmp);
  263. pFrameYUV->data[0]=bmp->pixels[0];
  264. pFrameYUV->data[1]=bmp->pixels[2];
  265. pFrameYUV->data[2]=bmp->pixels[1];
  266. pFrameYUV->linesize[0]=bmp->pitches[0];
  267. pFrameYUV->linesize[1]=bmp->pitches[2];
  268. pFrameYUV->linesize[2]=bmp->pitches[1];
  269. sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
  270. #if OUTPUT_YUV420P
  271. int y_size=pCodecCtx->width*pCodecCtx->height;
  272. fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y
  273. fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U
  274. fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V
  275. #endif
  276. SDL_UnlockYUVOverlay(bmp);
  277. SDL_DisplayYUVOverlay(bmp, &rect);
  278. }
  279. }
  280. av_free_packet(packet);
  281. }else{
  282. //Exit Thread
  283. thread_exit=1;
  284. }
  285. }else if(event.type==SDL_QUIT){
  286. thread_exit=1;
  287. }else if(event.type==SFM_BREAK_EVENT){
  288. break;
  289. }
  290. }
  291. sws_freeContext(img_convert_ctx);
  292. #if OUTPUT_YUV420P
  293. fclose(fp_yuv);
  294. #endif
  295. SDL_Quit();
  296. //av_free(out_buffer);
  297. av_free(pFrameYUV);
  298. avcodec_close(pCodecCtx);
  299. avformat_close_input(&pFormatCtx);
  300. return 0;
  301. }

结果

程序的运行效果如下。输出了摄像头的数据。

[转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

可以通过下面的宏定义来确定是否将解码后的YUV420P数据输出成文件:

  1. #define OUTPUT_YUV420P 0

可以通过下面的宏定义来确定使用VFW或者是Dshow打开摄像头:

  1. //'1' Use Dshow
  2. //'0' Use VFW
  3. #define USE_DSHOW 0

下载

 

Simplest FFmpeg Device 

项目主页

SourceForge:https://sourceforge.net/projects/simplestffmpegdevice/

Github:https://github.com/leixiaohua1020/simplest_ffmpeg_device

开源中国:http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_device

CSDN下载地址:

http://download.csdn.net/detail/leixiaohua1020/7994049

注:

本工程包含两个基于FFmpeg的libavdevice的例子:
 simplest_ffmpeg_grabdesktop:屏幕录制。
 simplest_ffmpeg_readcamera:读取摄像头。

更新-1.1(2015.1.9)=========================================

该版本中,修改了SDL的显示方式,弹出的窗口可以移动了。

CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8344695

更新-1.2 (2015.2.13)=========================================

这次考虑到了跨平台的要求,调整了源代码。经过这次调整之后,源代码可以在以下平台编译通过:

VC++:打开sln文件即可编译,无需配置。

cl.exe:打开compile_cl.bat即可命令行下使用cl.exe进行编译,注意可能需要按照VC的安装路径调整脚本里面的参数。编译命令如下。

  1. ::VS2010 Environment
  2. call "D:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
  3. ::include
  4. @set INCLUDE=include;%INCLUDE%
  5. ::lib
  6. @set LIB=lib;%LIB%
  7. ::compile and link
  8. cl simplest_ffmpeg_readcamera.cpp /MD /link SDL.lib SDLmain.lib avcodec.lib ^
  9. avformat.lib avutil.lib avdevice.lib avfilter.lib postproc.lib swresample.lib swscale.lib ^
  10. /SUBSYSTEM:WINDOWS /OPT:NOREF

MinGW:MinGW命令行下运行compile_mingw.sh即可使用MinGW的g++进行编译。编译命令如下。

  1. g++ simplest_ffmpeg_readcamera.cpp -g -o simplest_ffmpeg_readcamera.exe \
  2. -I /usr/local/include -L /usr/local/lib \
  3. -lmingw32 -lSDLmain -lSDL -lavformat -lavcodec -lavutil -lavdevice -lswscale

GCC(Linux):Linux命令行下运行compile_gcc.sh即可使用GCC进行编译。编译命令如下。

  1. gcc simplest_ffmpeg_readcamera.cpp -g -o simplest_ffmpeg_readcamera.out \
  2. -I /usr/local/include -L /usr/local/lib -lSDLmain -lSDL -lavformat -lavcodec -lavutil -lavdevice -lswscale

GCC(MacOS):MacOS命令行下运行compile_gcc_mac.sh即可使用GCC进行编译。Mac的GCC和Linux的GCC差别不大,但是使用SDL1.2的时候,必须加上“-framework Cocoa”参数,否则编译无法通过。编译命令如下。

  1. gcc simplest_ffmpeg_readcamera.cpp -g -o simplest_ffmpeg_readcamera.out \
  2. -framework Cocoa -I /usr/local/include -L /usr/local/lib -lSDLmain -lSDL -lavformat -lavcodec -lavutil -lavdevice -lswscale

PS:相关的编译命令已经保存到了工程文件夹中

此外,增加了MacOS下使用avfoundation读取摄像头的代码。

CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8445747

SourceForge上已经更新。

转自:http://blog.csdn.net/leixiaohua1020/article/details/39702113

[转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)的更多相关文章

  1. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)【转】

    转自:http://blog.csdn.net/leixiaohua1020/article/details/39702113 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[- ...

  2. 最简单的基于FFmpeg的AVDevice例子(屏幕录制)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...

  3. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...

  4. 最简单的基于FFmpeg的AVDevice样例(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice样例文章列表: 最简单的基于FFmpeg的AVDev ...

  5. 最简单的基于FFmpeg的AVfilter例子(水印叠加)

    ===================================================== 最简单的基于FFmpeg的AVfilter例子系列文章: 最简单的基于FFmpeg的AVfi ...

  6. 最简单的基于FFMPEG的转码程序

    本文介绍一个简单的基于FFmpeg的转码器.它可以将一种视频格式(包括封转格式和编码格式)转换为另一种视频格式.转码器在视音频编解码处理的程序中,属于一个比较复杂的东西.因为它结合了视频的解码和编码. ...

  7. 100行代码实现最简单的基于FFMPEG&plus;SDL的视频播放器(SDL1&period;x)【转】

    转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] ...

  8. 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

    http://blog.csdn.net/leixiaohua1020/article/details/25430449 本文介绍一个最简单的基于FFMPEG的音频编码器.该编码器实现了PCM音频采样 ...

  9. 最简单的基于FFmpeg的推流器(以推送RTMP为例)

    ===================================================== 最简单的基于FFmpeg的推流器系列文章列表: <最简单的基于FFmpeg的推流器(以 ...

随机推荐

  1. google应用商店的解决

    { "enabled_plugins": [ "SimpleReloadPlugin", "SimpleRefresh" ] } git c ...

  2. SOA之(4)——服务实现的途径

    服务实现的途径(Service Implementation Mediums) 将SOA看成是一个架构模型非常重要,它独立于任何技术平台.对于企业来说,可以根据它当前自身的技术优势来实现SOA,从而达 ...

  3. 给ie浏览器添加推荐浏览器提示

    <script type="text/javascript"> var isIE = !!window.ActiveXObject; var isIE6 = isIE ...

  4. ural 1119&period; Metro&lpar;动态规划&rpar;

    1119. Metro Time limit: 0.5 second Memory limit: 64 MB Many of SKB Kontur programmers like to get to ...

  5. 多种Timer的场景应用

    前言 今天讲讲各种Timer的使用. 三种Timer组件 .Net框架提供了三种常规Timer组件,分别是System.Windows.Forms.Timer.System.Timers.Timer和 ...

  6. Easy Finding POJ - 3740 (DLX)

    显然这是一道dfs简单题 或许匹配也能做 然而用了dancing links 显然这也是一道模板题 好的吧 调了一上午 终于弄好了模板 Easy Finding Time Limit: 1000MS ...

  7. python --- 10 &ast;args &ast;&ast;kwargs 命名空间 作用域 函数的嵌套

    函数进阶 1.   "*"  和  "**" ① 在形参位置时   都是聚合的作用 *args    位置参数→元组 **kwargs   关键字参数→字典 混 ...

  8. BZOJ4416 &lbrack;Shoi2013&rsqb;阶乘字符串 【序列自动机 &plus; 状压dp】

    题目链接 BZOJ4416 题解 建立序列自动机,即预处理数组\(nxt[i][j]\)表示\(i\)位置之后下一个\(j\)出现的位置 设\(f[i]\)表示合法字符集合为\(i\)的最短前缀,枚举 ...

  9. SQL注入科普

    技术交流,安全交友联系渔夫”小白“,微信号(xz116035) SQL注入介绍 SQL注入攻击是最为常见的Web应用安全漏洞之一,国外知名安全组织OWASP针对web应用安全漏洞进行了一个排名,SQL ...

  10. sql 流水号获取

    经常用到产生订单号等流水单号的场景,sqlserver实现流水号,如下: 表tb_b_Seq(流水号表): CREATE TABLE tb_b_Seq( Year int ,--年份 Month in ...