v4l2讀取攝像頭數據推送到流媒體服務器(使用RTMPdump)

RTMP是Real Time Messaging Protocol(實時消息傳輸協議),RTMPdump 封裝了RTMP協議的一些接口,使用戶使用RTMP協議更加的方便。關於RTMPdump的使用,可以參考博客

linux系統RTMPdump(libRTMP) 通過RTMP 發佈H264數據

linux系統RTMPdump(libRTMP) 通過RTMP 發佈FLV數據

在進行RTMP實驗的時候,需要先搭建好RTMP的編譯文件和一個RTMP服務器,具體可以參考:

linux 編譯安裝TRMPdump(libRTMP)

nginx 搭建rtmp流媒體服務器

要實現RTMP直播V4L2攝像頭數據,最簡單的方案就是使用FFMPEG,它已經實現了所有的功能,用戶只要使用一條命令就行了。但是對於有些嵌入式設備,沒有足夠的硬件資源來運行FFMPEG,對於這種情況,只能是自己來實現所需的所有接口。本文主要介紹在linux系統,用戶通過v4l2採集攝像頭的數據,然後對攝像頭數據進行x264編碼,再使用RTMPdump庫通過RTMP協議將編碼好的H264數據推送到RTMP服務器,最後客戶端從RTMP服務器中將數據拉下來,解碼,最後顯示出來,進而實現實時直播的目的。主要工作流程圖如下:


關於v4l2採集攝像頭數據並編碼成H264,可以參考:V4L2視頻採集與編碼——學習目錄及總結

主程序代碼如下:

/*=============================================================================  
 *     FileName: main.cpp
 *         Desc:  
 *       Author: licaibiao  
 *   LastChange: 2017-05-8   
 * =============================================================================*/  
#include "x264_encoder.h"
#include "v4l2_device.h"
#include "librtmp/log.h"
#include <signal.h>
#include <error.h>
 
int runflag=0;
static void sig_user(int signo){
    if(signo==SIGINT){
    	runflag=0;
        printf("received SIGINT\n");
  }
}
 
void rtmp_push_v4l2(){
	char url[]="rtmp://192.168.0.5:1935/live";
	int fps		= 30;
	int rate	= 333;
	int width	= 640;
	int height	= 480;
	int outSize	= 1024;
 
	int index=0;	
	unsigned int tick = 0;
	unsigned int tick_gap = 1000/fps;
	uint32_t now=0;
	uint32_t last_update=0;
 
	int fd;
	int len = 0;
	uint8_t *cam_buf;
	uint32_t pixelformat;
 
	cam_buf = (uint8_t*)malloc(1024*1024*3);
	memset(cam_buf, 0, 1024*1024*3);
	
	pixelformat = V4L2_PIX_FMT_YUYV;
	
    if(signal(SIGINT,sig_user)==SIG_ERR){
		perror("catch SIGINT err");
	}
 
	fd =open_camera();
	init_camera(fd, width, height);
	start_capture(fd);
		
	RTMP_CreatePublish(url,outSize,1,RTMP_LOGINFO);
	printf("connected \n");
	RTMP_InitVideoParams(width,height,fps, rate, pixelformat,false);
	printf("inited \n");
	runflag=1;
	//runflag=3;
		
	while(runflag){
		if(index!=0){
			RTMP_SendScreenCapture(cam_buf,height,tick, pixelformat, width, height);
			printf("send frame index -- %d\n",index);
		}
		last_update=RTMP_GetTime();
 
		read_frame(fd, cam_buf,&len);
 
		tick +=tick_gap;
		now=RTMP_GetTime();
		
		//usleep((tick_gap-now+last_update)*1000);
		usleep(1000);
		index++;
	}
 
	free(cam_buf);
	stop_capture(fd);
	close_camera_device(fd);
	RTMP_DeletePublish();
}
 
int main(){
	rtmp_push_v4l2();
	return 0;
}
 

我使用的是一個30萬像素的攝像頭,也就是輸出圖像尺寸爲640*480,它可以支持輸出MJPEG 和YUV422 兩種數據格式,因爲需要進行x264編碼,所以我這裏設置的是輸出YUV422(YUYV)格式。我自己搭建的RTMP服務器所在的地址爲:rtmp://192.168.0.5:1935/live。

有幾點需要注意:

1.在發送數據的時候,一定需要設置合適的幀率,因爲在有些平臺,可能編碼花費的時間較多,並達不到初始化設置的幀率,這樣在顯示的時候就會出現問題。 
2.需要客戶端先向服務端請求數據,然後再向服務器推送h264數據,否則會出現非常明顯的圖像延時,大約2~3秒。

工程目錄如下:

-bash-4.1# tree
.
├── include
│   ├── librtmp
│   │   ├── amf.h
│   │   ├── bytes.h
│   │   ├── dhgroups.h
│   │   ├── dh.h
│   │   ├── handshake.h
│   │   ├── http.h
│   │   ├── log.h
│   │   ├── rtmp.h
│   │   └── rtmp_sys.h
│   ├── librtmp_send264.h
│   ├── sps_decode.h
│   ├── v4l2_device.h
│   ├── x264_config.h
│   ├── x264_encoder.h
│   └── x264.h
├── lib
│   ├── librtmp.a
│   └── libx264.a
├── librtmp_send264.cpp
├── main.cpp
├── Makefile
├── v4l2_device.cpp
└── x264_encoder.cpp

程序運行如下:

-bash-4.1# ./test 
 
camera driver name is : uvcvideo
camera device name is : UVC Camera (046d:0825)
camera bus information: usb-0000:00:1a.0-1.1
 
support device 1.YUV 4:2:2 (YUYV)
support device 2.MJPEG
 
n_buffer = 4
connected 
x264 [warning]: VBV maxrate specified, but no bufsize, ignored
x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
x264 [info]: profile High 4:2:2, level 3.0, 4:2:2 8-bit
inited 
^Creceived SIGINT
select received SIGINT 
x264 [info]: frame I:1     Avg QP:36.90  size:  3106
x264 [info]: frame P:55    Avg QP:25.29  size:  1070
x264 [info]: mb I  I16..4: 25.9% 72.0%  2.1%
x264 [info]: mb P  I16..4:  3.7%  2.5%  0.0%  P16..4: 20.0%  4.0%  0.6%  0.0%  0.0%    skip:69.1%
x264 [info]: final ratefactor: 24.32
x264 [info]: 8x8 transform intra:47.2% inter:32.7%
x264 [info]: coded y,uvDC,uvAC intra: 18.5% 41.6% 7.7% inter: 2.0% 10.7% 0.0%
x264 [info]: i16 v,h,dc,p: 27% 51% 12% 11%
x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 13% 45% 30%  2%  1%  1%  3%  1%  4%
x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 54% 12%  2%  2%  2%  4%  1%  4%
x264 [info]: i8c dc,h,v,p: 61% 19% 17%  2%
x264 [info]: Weighted P-Frames: Y:0.0% UV:0.0%
x264 [info]: kb/s:265.47

客戶端直接使用VLC播放器,效果如下:
在這裏插入圖片描述
需要完整工程下載鏈接:
使用RTMPdump(libRTMP)直播來自v4l2的攝像頭數據

作者:li_wen01
原文:https://blog.csdn.net/li_wen01/article/details/71548079

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章