V4L2採集YUYV資料—X264編碼H264視訊例項
前幾天在網上買個羅技的C270攝像頭,它支援YUYV(YUV422)和JPEG資料輸出。它規格書上寫的是支援HD720P(1280*720畫素),在實際的除錯過程中,我使用該解析度會導致資料採集過慢。這裡需要注意一下,羅技的攝像頭C270在有些虛擬機器上使用是有異常的,有些是不能對映到虛擬機器上,有些是對映過去操作非常緩慢。因為之前在自己的開發板上除錯過YUV420的攝像頭,在此基礎上改為YUYV資料格式,除錯的時候還是遇到不少的問題。
在PC上編譯X264,可以直接執行下面三條命令:
./configure --enable-shared
make
make install
下面貼出x264部分的程式碼:
/*============================================================================= # FileName: h264encoder.c # Desc: this program aim to get image from USB camera, # used the V4L2 interface. # Author: licaibiao # Version: # LastChange: 2017-02-21 =============================================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "./include/h264encoder.h" int WIDTH = 640; int HEIGHT = 480; void compress_begin(Encoder *en, int width, int height) { en->param = (x264_param_t *) malloc(sizeof(x264_param_t)); en->picture = (x264_picture_t *) malloc(sizeof(x264_picture_t)); x264_param_default(en->param); //set default param //en->param->rc.i_rc_method = X264_RC_CQP; // en->param->i_log_level = X264_LOG_NONE; en->param->i_threads = X264_SYNC_LOOKAHEAD_AUTO; en->param->i_width = width; //set frame width en->param->i_height = height; //set frame height WIDTH = width; HEIGHT = height; //en->param->i_frame_total = 0; //en->param->i_keyint_max = 10; en->param->rc.i_lookahead = 0; //en->param->i_bframe = 5; //en->param->b_open_gop = 0; //en->param->i_bframe_pyramid = 0; //en->param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; //en->param->rc.i_bitrate = 1024 * 10;//rate 10 kbps en->param->i_fps_num = 30; en->param->i_fps_den = 1; en->param->i_csp = X264_CSP_I422; x264_param_apply_profile(en->param, x264_profile_names[4]); if ((en->handle = x264_encoder_open(en->param)) == 0) { return; } /* Create a new pic */ x264_picture_alloc(en->picture, X264_CSP_I422, en->param->i_width, en->param->i_height); } int compress_frame(Encoder *en, int type, uint8_t *in, uint8_t *out) { x264_picture_t pic_out; int index_y, index_u, index_v; int num; int nNal = -1; int result = 0; int i = 0; static long int pts = 0; uint8_t *p_out = out; char *y = en->picture->img.plane[0]; char *u = en->picture->img.plane[1]; char *v = en->picture->img.plane[2]; char * ptr; index_y = 0; index_u = 0; index_v = 0; num = WIDTH * HEIGHT * 2 - 4 ; for(i=0; i<num; i=i+4) { *(y + (index_y++)) = *(in + i); *(u + (index_u++)) = *(in + i + 1); *(y + (index_y++)) = *(in + i + 2); *(v + (index_v++)) = *(in + i + 3); } switch (type) { case 0: en->picture->i_type = X264_TYPE_P; break; case 1: en->picture->i_type = X264_TYPE_IDR; break; case 2: en->picture->i_type = X264_TYPE_I; break; default: en->picture->i_type = X264_TYPE_AUTO; break; } en->picture->i_pts = pts++; if (x264_encoder_encode(en->handle, &(en->nal), &nNal, en->picture, &pic_out) < 0) { return -1; } for (i = 0; i < nNal; i++) { memcpy(p_out, en->nal[i].p_payload, en->nal[i].i_payload); p_out += en->nal[i].i_payload; result += en->nal[i].i_payload; } return result; } void compress_end(Encoder *en) { if (en->handle) { x264_encoder_close(en->handle); } if (en->picture) { x264_picture_clean(en->picture); free(en->picture); en->picture = 0; } if (en->param) { free(en->param); en->param = 0; } }
上面的程式碼是配置x264編碼器的,有下面幾個地方需要特別注意:
(1)CSP引數的配置
en->param->i_csp = X264_CSP_I422;
在X264中預設的i_csp值是3,也就是X264_CSP_NV12 的值,如果採用YUYV(422)輸入格式,這個值一定需要重新設定,不然會出現錯誤提示:x264 [error]: Invalid input colorspace 。這是因為在x264核心中他會把輸入格式裝換為下面三種中的一種:X264_CSP_NV12,X264_CSP_NV16,X264_CSP_I444.轉換如下:(2)profile型別設定static int x264_frame_internal_csp( int external_csp ) { switch( external_csp & X264_CSP_MASK ) { case X264_CSP_NV12: case X264_CSP_NV21: case X264_CSP_I420: case X264_CSP_YV12: return X264_CSP_NV12; case X264_CSP_NV16: case X264_CSP_I422: case X264_CSP_YV16: case X264_CSP_V210: return X264_CSP_NV16; case X264_CSP_I444: case X264_CSP_YV24: case X264_CSP_BGR: case X264_CSP_BGRA: case X264_CSP_RGB: return X264_CSP_I444; default: return X264_CSP_NONE; } }
x264_param_apply_profile(en->param, x264_profile_names[4]);
在YUV422中,它不支援baseline,預設設定會提示:x264 [error]: baseline profile doesn't support 4:2:2 可以設定下面的其他引數:x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 };
(3)圖片記憶體分配
這裡的第二個引數一定要與你的輸入格式先對應,不然的話會出現記憶體溢位的錯誤。因為預設的分配圖片記憶體大小是YUV420的。以640*480 解析度來舉例,YUV420 分配一幀影象的記憶體是450K,而我們YUV422的資料量是600K。x264_picture_alloc(en->picture, X264_CSP_I422, en->param->i_width, en->param->i_height);
(4)Y,U,V 資料需要分離
for(i=0; i<num; i=i+4)
{
*(y + (index_y++)) = *(in + i);
*(u + (index_u++)) = *(in + i + 1);
*(y + (index_y++)) = *(in + i + 2);
*(v + (index_v++)) = *(in + i + 3);
}
YUYV的資料是交錯儲存的,因此需要把他們分離出來單獨儲存,如果這裡不做處理,影象就會出現異常。(5)i_pts 引數需要遞增
en->picture->i_pts = pts++;
i_pts = pts的引數是需要遞增的,不讓回出現警告:x264 [warning]: non-strictly-monotonic PTS完整的編譯執行結果如下:
[[email protected] test]# ls
h264encoder.c include lib main.c Makefile out
[[email protected] test]# make
gcc -g -c -o main.o main.c
gcc -g -c -o h264encoder.o h264encoder.c
gcc -g -o x264_test main.o h264encoder.o -lpthread -lx264 -lm
[[email protected] test]# ls
h264encoder.c h264encoder.o include lib main.c main.o Makefile out x264_test
[[email protected] test]# ./x264_test
camera driver name is : uvcvideo
camera device name is : UVC Camera (046d:0825)
camera bus information: usb-0000:00:1a.0-1.1
n_buffer = 4
x264 [warning]: lookaheadless mb-tree requires intra refresh or infinite keyint
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
spend time 85.082031 s
x264 [info]: frame I:8 Avg QP:20.27 size: 21592
x264 [info]: frame P:503 Avg QP:21.18 size: 3119
x264 [info]: frame B:1485 Avg QP:22.03 size: 952
x264 [info]: consecutive B-frames: 0.8% 0.0% 0.0% 99.2%
x264 [info]: mb I I16..4: 11.9% 55.2% 32.9%
x264 [info]: mb P I16..4: 0.4% 0.2% 0.1% P16..4: 44.8% 7.9% 8.5% 0.0% 0.0% skip:38.2%
x264 [info]: mb B I16..4: 0.0% 0.0% 0.0% B16..8: 25.9% 0.6% 0.1% direct: 1.7% skip:71.7% L0:51.6% L1:47.0% BI: 1.4%
x264 [info]: 8x8 transform intra:46.7% inter:95.7%
x264 [info]: coded y,uvDC,uvAC intra: 60.5% 87.6% 59.7% inter: 5.7% 23.2% 0.9%
x264 [info]: i16 v,h,dc,p: 4% 8% 1% 87%
x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 16% 39% 12% 3% 5% 4% 10% 4% 7%
x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 24% 41% 8% 3% 4% 3% 8% 3% 4%
x264 [info]: i8c dc,h,v,p: 50% 22% 21% 6%
x264 [info]: Weighted P-Frames: Y:0.2% UV:0.0%
x264 [info]: ref P L0: 40.2% 4.8% 39.3% 15.7%
x264 [info]: ref B L0: 65.6% 20.4% 14.0%
x264 [info]: ref B L1: 91.2% 8.8%
x264 [info]: kb/s:379.47
[[email protected] test]#
這裡設定的解析度是640*480 ,這樣採集資料比較快。我編碼2000幀資料需要的是大約85s,幀率大約在23fps 。也不知道具體是什麼原因導致耗時這麼長時間。視訊執行如下:
相關推薦
V4L2採集YUYV資料—X264編碼H264視訊例項
前幾天在網上買個羅技的C270攝像頭,它支援YUYV(YUV422)和JPEG資料輸出。它規格書上寫的是支援HD720P(1280*720畫素),在實際的除錯過程中,我使用該解析度會導致資料採集過慢。這裡需要注意一下,羅技的攝像頭C270在有些虛擬機器上使用是有異常的
YUYV資料—X264編碼H264視訊例項
x264庫的編譯可以見之前部落格:http://blog.csdn.net/li_wen01/article/details/53571929 在PC上編譯X264,可以直接執行下面三條命令: ./configure --enable-shared make make install
android編碼h264(一):使用x264編碼yuv為h264資料的例子(軟編碼)
先說下簡單流程: 1.camera回撥nv21 yuv; 2.nv21轉yuv420; 3.x264編碼h264,回調回java層; 4.寫檔案,生成.h264檔案; 5.使用vlc等播放器播放。 android java層的程式碼比較簡單,簡單說下: 這個de
V4L2視訊採集與H.264編碼原始碼大放送:Linux視訊採集與編碼(三)
這幾天的努力也算沒有白費,現在我將貢獻出我的成果,當然程式碼很大一部分都不是我寫的。 V4L2視訊採集我參考了V4L2官方原始碼,H.264編碼我使用了開源編碼庫x264,並參考了網上的一些例子。 但
使用ffmpeg將BMP圖片編碼為x264視訊檔案,將H264視訊儲存為BMP圖片,yuv視訊檔案儲存為圖片的程式碼
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #ifdef __cplusplus extern "C" { #endif #include
基於iOS的網路音視訊實時傳輸系統(三)- VideoToolbox編碼音視訊資料為H264、AAC
server端 -- 編碼音視訊資料為H264、AAC 這部分花了好多時間,本身就不具備這方面的相關知識,查閱了不少資料,不過關於VideoToolbox和AudioToolbox方面的編碼資料寥寥無幾,雖然網上搜索結果看似特別多,其實一看 內容也大同小異,建議還是看看官方
FFmpeg 4.0.2編碼YUV序列為H264視訊檔案
/****************************** 功能:編碼YUV序列為h264視訊檔案 FFmpeg:4.0.2 ******************************/ #include <iostream> extern "C" { #include &
android平臺下基於ffmpeg採集Camera資料編碼成H.264推流到RTMP伺服器
音視訊實踐學習 android全平臺編譯ffmpeg以及x264與fdk-aac實踐 ubuntu下使用nginx和nginx-rtmp-module配置直播推流伺服器 android全平臺編譯ffmpeg合併為單個庫實踐 android-studio使用c
V4L2採集+編碼壓縮(M-JPEG和H.264壓縮效能比較)
Linux下,一般的普通USB攝像頭V4L2視訊採集有兩種方式:V4L2_PIX_FMT_MJPEG和V4L2_PIX_FMT_YUYV。 V4L2_PIX_FMT_MJPEG採集方式得到的是經過M
H264視訊編碼成MP4檔案
最近需要將H264視訊編碼成MP4格式。研究了一下,一種方法是採用ffmpeg庫,可以先將H264檔案解碼,再編碼生成MP4檔案,但這種方式效率較低,10M的視訊可能需要幾秒鐘才能完成。另一種方式根據MP4檔案協議直接將H264包封裝成MP4格式,由於是直接
深入淺出理解視訊編碼H264結構
編碼流程: 那麼 H.264 其編解碼流程是怎麼樣的呢?其實可以主要分為 5 部分: 幀間和幀內預測(Estimation)、變換(Transform)和反變換、量化(Quantization)和反量化、環路濾波(Loop Filter)、熵編碼(Entropy Coding)。 看起來很高深的樣子,實際上
如何從H264原始資料SPS裡面得到視訊的長寬
有這樣一種需求,給你一個h264原始資料檔案,讓你直接播放出來,如何實現? 思路是這樣的,H264原始資料格式都是 0x00000001後面跟0x67 0x68 0x65 0x41這樣的資料,解碼需要一個完整的NAL資料單元,我們需要將每個0x00000001以及下一個0x
android下將v4l2採集的yuv資料轉成jpg圖片
int write_JPEG_file (constchar* filename,unsignedchar* yuvData,int quality,int image_width,int image_height) { LOG("write_JPEG_file 1 \n"); struct jpeg_
YUV資料流編碼成H264
自己使用ffmpeg進行編碼,在網上搜索到了雷霄驊大神,他的部落格內幾乎全是關於ffmpeg的,內容很全面,不過ffmpeg更新很快,他部落格上的有些程式碼,不太適合了。 但是,他提供了更新後的程式碼,自己使用的是如下的程式碼例子,地址在最後面。 檔案中有兩個例子,我都實驗
H264視訊編碼的基本瞭解
參考:https://www.axis.com/files/whitepaper/wp_h264_34203_cn_0901_lo.pdf 因為視訊是有圖片不斷切換產生的,現在一張圖片都有幾兆,這樣一次傳輸一張完整圖片的成本太大,會產生大量的流量。因此會出現壓縮編碼的需求。
Android視訊編碼--H264編碼
Android視訊編碼–H264編碼 Android中的H264編碼有兩種編碼方式: 硬編碼 軟編碼 1.硬編碼 Android中的H264硬編碼主要是通過自身提供的API,呼叫底層的硬體模組實現編碼,不使用CPU。 採用硬編碼的核心示例程式
基於RTP的H264視訊資料打包解包類
最近考慮使用RTP替換原有的高清視訊傳輸協議,遂上網查詢有關H264視訊RTP打包、解包的文件和程式碼。功夫不負有心人,找到不少有價值的文件和程式碼。參考這些資料,寫了H264 RTP打包類、解包類,實現了單個NAL單元包和FU_A分片單元包。對於丟包處理,採用簡
RTMP資料流提取RTMP視訊流組成H264視訊檔案
首先我們獲得h264的流,在監聽裡,我們通過引數可以獲得RTMP包 IStreamPacket,呼叫getData()方法直接獲得包資料 放入IOBuffer。以下是提取並修改資料存成h264檔案的步驟 1. 新增監聽 IStreamListener 2. 通過IOBu
android硬編碼h264資料,並使用rtp推送資料流,實現一個簡單的直播-MediaCodec(一)
寫在前面:我並非專業做流媒體的coder,對流媒體行業無比崇拜,只是做了幾年安卓車載ROM,對安卓AV開發算是略懂。本篇部落格是我對MediaCodec編解碼和rtp推流的一次嘗試,希望能給有需要的朋友一些細微的幫助,不喜勿噴,如果有不對的地方希望大神指正共
使用 ffmpeg 進行網路推流:拉流->解封裝->解碼->處理原始資料(音訊、視訊)->編碼->編碼->推流
簡要說明: 1、可拉流:rtmp、rtsp、http 2、可推流: #include "stdafx.h" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #