天天看點

FFMPEG(一) 從V4L2捕獲攝像頭資料

系列相關博文:

    最近在學習FFMPEG,發現網上的很多例子都是基于讀檔案的。直接從攝像頭中讀取資料的卻很少。之前寫過通過v4l2采集攝像頭資料然後調用x264編碼成視訊檔案的例子。在FFMPEG中,它将很多的V4L2操作函數已經封裝好,這裡提供一個最簡的例程。需要注意的是,我采用的FFMPEG的版本是最新的ffmpeg-3.2.4 版本,不同版本的庫,接口函數有有些不一樣。

/*============================================================================= 

#     FileName: read_device.c 

#         Desc: use ffmpeg read a frame data from v4l2  

#       Author: licaibiao 

#   LastChange: 2017-03-15  

=============================================================================*/  

#include <stdio.h>  

#include <string.h>  

#include <stdlib.h>  

#include <unistd.h>  

#include "avformat.h"  

#include "avcodec.h"  

#include "avdevice.h"  

char* input_name= "video4linux2";  

char* file_name = "/dev/video0";  

char* out_file  = "test.jpeg";  

void captureOneFrame(void){  

    AVFormatContext *fmtCtx = NULL;      

    AVPacket *packet;   

    AVInputFormat *inputFmt;  

    FILEFILE *fp;   

    int ret;  

    inputFmt = av_find_input_format (input_name);      

    if (inputFmt == NULL)    {          

        printf("can not find_input_format\n");          

        return;      

    }      

    if (avformat_open_input ( &fmtCtx, file_name, inputFmt, NULL) < 0){  

        printf("can not open_input_file\n");         return;      

    }  

    /* print device information*/  

    av_dump_format(fmtCtx, 0, file_name, 0);  

    packet = (AVPacket *)av_malloc(sizeof(AVPacket));      

    av_read_frame(fmtCtx, packet);   

    printf("data length = %d\n",packet->size);     

    fp = fopen(out_file, "wb");      

    if (fp < 0)    {          

        printf("open frame data file failed\n");          

        return ;      

    fwrite(packet->data, 1, packet->size, fp);      

    fclose(fp);      

    av_free_packet(packet);      

    avformat_close_input(&fmtCtx);  

 }   

int main(void){      

    avcodec_register_all();      

    avdevice_register_all();      

    captureOneFrame();      

    return 0;  

}  

    Makefile檔案如下:

OUT_APP      = test  

INCLUDE_PATH = /usr/local/include/  

INCLUDE = -I$(INCLUDE_PATH)libavutil/ -I$(INCLUDE_PATH)libavdevice/ \  

            -I$(INCLUDE_PATH)libavcodec/ -I$(INCLUDE_PATH)libswresample \  

            -I$(INCLUDE_PATH)libavfilter/ -I$(INCLUDE_PATH)libavformat \  

            -I$(INCLUDE_PATH)libswscale/  

FFMPEG_LIBS = -lavformat -lavutil -lavdevice -lavcodec -lswresample -lavfilter -lswscale  

SDL_LIBS    =   

LIBS        = $(FFMPEG_LIBS)$(SDL_LIBS)  

COMPILE_OPTS = $(INCLUDE)  

C            = c  

OBJ          = o  

C_COMPILER   = cc  

C_FLAGS      = $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS)  

LINK         = cc -o   

LINK_OPTS    = -lz -lm  -lpthread  

LINK_OBJ     = read_device.o   

.$(C).$(OBJ):  

    $(C_COMPILER) -c -g $(C_FLAGS) $<  

$(OUT_APP): $(LINK_OBJ)  

    $(LINK)$@  $(LINK_OBJ)  $(LIBS) $(LINK_OPTS)  

clean:  

        -rm -rf *.$(OBJ) $(OUT_APP) core *.core *~  *.jpeg  

    編譯運作結果如下:

licaibiao@ubuntu:~/test/FFMPEG/device$ ./test   

[video4linux2,v4l2 @ 0x1d18040] Time per frame unknown  

Input #0, video4linux2,v4l2, from '/dev/video0':  

  Duration: N/A, bitrate: N/A  

    Stream #0:0: Video: mjpeg, none, 640x480, 1000k tbn  

data length = 27697  

licaibiao@ubuntu:~/test/FFMPEG/device$ ls  

Makefile  read_device.c  read_device.o  test  test.jpeg  webcm.c  

licaibiao@ubuntu:~/test/FFMPEG/device$   

    我使用的攝像頭輸出的是mjpeg格式資料,将它儲存到test.jpeg 檔案。打開如下:

FFMPEG(一) 從V4L2捕獲攝像頭資料

繼續閱讀