Linux下ffmpeg庫開發(fā)之讀取攝像頭數據
?FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,并能將其轉化為流的開源計算機程序。采用LGPL或GPL許可證。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質量,libavcodec里很多code都是從頭開發(fā)的。
1.ffmpeg源碼安裝
??安裝ffmpeg庫之前需要先安裝yasm庫和x264庫。
?1.1 Yasm安裝
??下載地址:http://yasm.tortall.net/
??安裝yasm
#解壓
tar xvf /mnt/hgfs/ubuntu/software_pack/yasm-1.3.0.tar.gz
#配置信息,生成Makefile
./configure
#編譯安裝
make && make install
?1.2 x264安裝
??下載地址:https://www.videolan.org/developers/x264.html
??安裝x264
#解壓
tar xvf /mnt/hgfs/ubuntu/software_pack/x264-master.tar.bz2
#配置信息,生成Makefile
./configure --prefix=$PWD/_install --enable-shared --enable-static
??若配置時提示找不到nasm則下載nasm
??安裝nasm
??nasm下載地址:https://www.nasm.us/pub/nasm/releasebuilds/2.15.03/
?Netwide Assembler (簡稱 NASM)是一款基于x86架構的匯編與反匯編軟件。它可以用來編寫16位(8086、80286等)、32位(IA-32)和64位(x86_64)的程序。 NASM被認為是Linux平臺上最受歡迎的匯編工具之一。
NASM可以輸出包括通用對象文件格式(COFF)、OMF(Relocatable Object Module Format,用于80x86系列處理器上)、a.out、可執(zhí)行與可鏈接格式(ELF)、Mach-O、二進制文件(.bin,二進制磁盤映像,用于編譯操作系統)等多種二進制格式,而地址無關代碼僅支持ELF對象文件。 NASM也有自己的稱為RDOFF(Relocatable Dynamic Object File Format)的二進制格式。
tar xvf /mnt/hgfs/ubuntu/software_pack/nasm-2.15.03.tar.gz
./autogen.sh
./configure
make && make install
?再重新編譯x264,按照1.2小結操作:
#解壓
tar xvf /mnt/hgfs/ubuntu/software_pack/x264-master.tar.bz2
#配置信息,生成Makefile
./configure --prefix=$PWD/_install --enable-shared --enable-static
make && make install
??拷貝相關庫到系統目錄下
[wbyq@wbyq _install]$ sudo cp ./lib/*.so* /usr/lib -fdv
?1.3 ffmpeg安裝
??為了保證后續(xù)音視頻錄制正常,需要先安裝聲卡驅動。
sudo apt-get install libasound2-dev
??下載地址:http://www.ffmpeg.org/download.html
?編譯安裝ffmpeg
#解壓
tar xvf /mnt/hgfs/ubuntu/software_pack/ffmpeg-4.2.5.tar.bz2
#配置信息,生成Makefile
./configure --enable-static --enable-shared --prefix=$PWD/_install --extra-cflags=-I/home/wbyq/src_pack/x264-master/_install/include --extra-ldflags=-L/home/wbyq/src_pack/x264-master/_install/lib --enable-ffmpeg --enable-libx264 --enable-gpl
#編譯安裝
make && make install
?拷貝相關庫到系統目錄下
[wbyq@wbyq _install]$ sudo cp ./bin/ffmpeg /usr/bin/
[wbyq@wbyq _install]$ sudo cp lib/*.so* /usr/lib -rfdv
2. 查看ffmpeg版本信息
[wbyq@wbyq ~]$ ffmpeg -version
ffmpeg version 4.2.5 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
configuration: --enable-static --enable-shared --prefix=/home/wbyq/src_pack/ffmpeg-4.2.5/_install --extra-cflags=-I/home/wbyq/src_pack/x264-master/_install/include --extra-ldflags=-L/home/wbyq/src_pack/x264-master/_install/lib --enable-ffmpeg --enable-libx264 --enable-gpl
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
3.ffmpeg代碼開發(fā)讀取攝像頭數據通過SDL顯示
?3.1 參考代碼
#include
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include
#include
#include
#include
#include
#include
#include
#define VIDEO_DEV "/dev/video2"
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;//互斥鎖
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//條件變量
typedef enum
{
false=0,
true,
}bool;
int width;
int height;
int size;
unsigned char *rgb_buff=NULL;
unsigned char video_flag=1;
void *Video_CollectImage(void *arg);
int main()
{
/*創(chuàng)建攝像頭采集線程*/
pthread_t pthid;
pthread_create(&pthid,NULL,Video_CollectImage, NULL);
pthread_detach(pthid);/*設置分離屬性*/
sleep(1);
while(1)
{
if(width!=0 && height!=0 && size!=0)break;
if(video_flag==0)return 0;
}
printf("image:%d * %d,%dn",width,height,size);
unsigned char *rgb_data=malloc(size);
/*創(chuàng)建窗口 */
SDL_Window *window=SDL_CreateWindow("SDL_VIDEO", SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,800,480,SDL_WINDOW_ALLOW_HIGHDPI|SDL_WINDOW_RESIZABLE);
/*創(chuàng)建渲染器*/
SDL_Renderer *render=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
/*清空渲染器*/
SDL_RenderClear(render);
/*創(chuàng)建紋理*/
SDL_Texture*sdltext=SDL_CreateTexture(render,SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMING,width,height);
bool quit=true;
SDL_Event event;
SDL_Rect rect;
while(quit)
{
while(SDL_PollEvent(&event))/*事件監(jiān)測*/
{
if(event.type==SDL_QUIT)/*退出事件*/
{
quit=false;
video_flag=0;
pthread_cancel(pthid);/*殺死指定線程*/
continue;
}
}
if(!video_flag)
{
quit=false;
continue;
}
pthread_mutex_lock(&fastmutex);//互斥鎖上鎖
pthread_cond_wait(&cond,&fastmutex);
memcpy(rgb_data,rgb_buff,size);
pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖
SDL_UpdateTexture(sdltext,NULL,rgb_data,width);
//SDL_RenderCopy(render, sdltext, NULL,NULL); // 拷貝紋理到渲染器
SDL_RenderCopyEx(render, sdltext,NULL,NULL,0,NULL,SDL_FLIP_NONE);
SDL_RenderPresent(render); // 渲染
}
SDL_DestroyTexture(sdltext);/*銷毀紋理*/
SDL_DestroyRenderer(render);/*銷毀渲染器*/
SDL_DestroyWindow(window);/*銷毀窗口 */
SDL_Quit();/*關閉SDL*/
pthread_mutex_destroy(&fastmutex);/*銷毀互斥鎖*/
pthread_cond_destroy(&cond);/*銷毀條件變量*/
free(rgb_buff);
free(rgb_data);
return 0;
}
void *Video_CollectImage(void *arg)
{
int res=0;
AVFrame *Input_pFrame=NULL;
AVFrame *Output_pFrame=NULL;
printf("pth:%sn",avcodec_configuration());
/*注冊設備*/
avdevice_register_all();
/*查找輸入格式*/
AVInputFormat *ifmt=av_find_input_format("video4linux2");
if(ifmt==NULL)
{
printf("av_find_input_format failedn");
video_flag=0;
return 0;
}
/*打開輸入流并讀取頭部信息*/
AVFormatContext *ps=NULL;
res=avformat_open_input(&ps,VIDEO_DEV,ifmt,NULL);
if(res)
{
printf("open input failedn");
video_flag=0;
return 0;
}
/*查找流信息*/
res=avformat_find_stream_info(ps,NULL);
if(res)
{
printf("find stream failedn");
video_flag=0;
return 0;
}
/*打印有關輸入或輸出格式信息*/
av_dump_format(ps, 0, "video4linux2", 0);
/*尋找視頻流*/
int videostream=-1;
videostream=av_find_best_stream(ps,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
printf("videostram=%dn",videostream);
/*尋找編解碼器*/
AVCodec *video_avcodec=NULL;/*保存解碼器信息*/
AVStream *stream = ps->streams[videostream];
AVCodecContext *context=stream->codec;
video_avcodec=avcodec_find_decoder(context->codec_id);
if(video_avcodec==NULL)
{
printf("find video decodec failedn");
video_flag=0;
return 0;
}
/*初始化音視頻解碼器*/
res=avcodec_open2(context,video_avcodec,NULL);
if(res)
{
printf("avcodec_open2 failedn");
video_flag=0;
return 0;
}
AVPacket *packet=av_malloc(sizeof(AVPacket));/*分配包*/
AVFrame *frame=av_frame_alloc();/*分配視頻幀*/
AVFrame *frameyuv=av_frame_alloc();/*申請YUV空間*/
/*分配空間,進行圖像轉換*/
width=context->width;
height=context->height;
int fmt=context->pix_fmt;/*流格式*/
size=av_image_get_buffer_size(AV_PIX_FMT_YUV420P,width,height,16);
unsigned char *buff=NULL;
printf("w=%d,h=%d,size=%dn",width,height,size);
buff=av_malloc(size);
rgb_buff=malloc(size);//保存RGB顏色數據
/*存儲一幀圖像數據*/
av_image_fill_arrays(frameyuv->data,frameyuv->linesize,buff,AV_PIX_FMT_YUV420P,width,height, 16);
/*轉換上下文,使用sws_scale()執(zhí)行縮放/轉換操作。*/
struct SwsContext *swsctx=sws_getContext(width,height, fmt,width,height, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);
/*讀幀*/
int go=0;
int Framecount=0;
printf("read fream buffn");
while(av_read_frame(ps,packet)>=0 && video_flag)
{
Framecount++;
if(packet->stream_index == AVMEDIA_TYPE_VIDEO)/*判斷是否為視頻*/
{
/*解碼一幀視頻數據。輸入一個壓縮編碼的結構體AVPacket,輸出一個解碼后的結構體AVFrame*/
res=avcodec_decode_video2(ps->streams[videostream]->codec,frame,&go,packet);
if(res<0)
{
printf("avcodec_decode_video2 failedn");
break;
}
if(go)
{
/*轉換像素的函數*/
sws_scale(swsctx,(const uint8_t * const*)frame->data,frame->linesize,0,height,frameyuv->data,frameyuv->linesize);
pthread_mutex_lock(&fastmutex);//互斥鎖上鎖
memcpy(rgb_buff,buff,size);
pthread_cond_broadcast(&cond);//廣播喚醒所有線程
pthread_mutex_unlock(&fastmutex);//互斥鎖解鎖
}
}
}
sws_freeContext(swsctx);/*釋放上下文*/
av_frame_free(&frameyuv);/*釋放YUV空間*/
av_packet_unref(packet);/*釋放包*/
av_frame_free(&frame);/*釋放視頻幀*/
avformat_close_input(&ps);/*關閉流*/
video_flag=0;
pthread_exit(NULL);
}
?3.2 Makefile文件
OBJ=get_cameraimage.c
CFLAGS =-I/home/wbyq/src_pack/SDL2-2.0.14/_install/include -I/home/wbyq/src_pack/SDL2-2.0.14/_install/include/SDL2 -L/home/wbyq/src_pack/SDL2-2.0.14/_install/lib
CFLAGS +=-L/home/wbyq/src_pack/SDL2_image-2.0.5/_install/lib -I/home/wbyq/src_pack/SDL2_image-2.0.5/_install/include -I/home/wbyq/src_pack/SDL2_image-2.0.5/_install/include/SDL2
CFLAGS+=-lSDL2 -lpthread -lm -ldl -lSDL2_image -lavcodec -lavfilter -lavutil -lswresample -lavdevice -lavformat -lpostproc -lswscale -lpthread -lstdc++ -lm -lasound
CFLAGS+=-I/home/wbyq/src_pack/ffmpeg-4.2.5/_install/include -L/home/wbyq/src_pack/ffmpeg-4.2.5/_install/lib -I/home/wbyq/src_pack/SDL2-2.0.14/_install/include -I/home/wbyq/src_pack/SDL2-2.0.14/_install/include/SDL2
app:
gcc $(OBJ) $(CFLAGS)
?3.3 運行效果
-
Linux
+關注
關注
87文章
11292瀏覽量
209326 -
攝像頭
+關注
關注
59文章
4836瀏覽量
95599 -
ffmpeg
+關注
關注
0文章
46瀏覽量
7395
發(fā)布評論請先 登錄
相關推薦
評論