1、直播流程整體流程?
1.1 數(shù)據(jù)采集(通常是攝像頭和錄屏)
1.2 編碼,也叫視頻壓縮(采用H264?編解碼協(xié)議,格式AVC),H265壓縮比例更高,自行選擇,使用的MediaCodec,Android原生api
1.3 傳輸,使用的是Netty網(wǎng)絡(luò)通訊協(xié)議,基于socket封裝的非常好網(wǎng)絡(luò)框架,數(shù)據(jù)傳輸序列化用的protobuf(主要用與Android和ios跨平臺傳輸byte[]數(shù)據(jù),如果不涉及跨平臺,使用Netty即可)
1.4 解碼 網(wǎng)絡(luò)傳遞過來的byte數(shù)據(jù)流,解析出視頻數(shù)據(jù)流,由MediaCodec解碼
1.5 渲染顯示,自定義suface,交給MediaCodec渲染即可
2、首選,我們來看第一步,數(shù)據(jù)采集
2.1 啟動(dòng)相機(jī),此處使用的是camera1,camera2難使用,資料少,不會(huì)的還是建議用camera1
private void startCamera(int type) {
????releaseCamera();
if (mTextureView.getSurfaceTexture() ==null){
????????return;
}
cameraType = type;
try {
????mCamera =Camera.open(type);
????mCamera.setPreviewCallback(this);
????mCamera.setDisplayOrientation(90);
????Camera.Parameters parameters =mCamera.getParameters();
????parameters.setPreviewFormat(ImageFormat.NV21);
????if (cameraType ==CAMERA_FACING_BACK){
????????LogUtils.i("fangzhi","CAMERA_FACING_BACK FOCUS_MODE_CONTINUOUS_VIDEO");
????????parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
????}
if (size ==null) {
????????size =CameraManager.getOptimalSize(parameters.getSupportedPreviewSizes(),mWidth,mHeight);
????????float diff = (float)size.height /size.width - (float)ScreenUtils.getScreenWidth() ????????/ScreenUtils.getScreenHeight();
????????if (diff >=0.05 &&Build.VERSION.SDK_INT
????????????????mWidth =640;
????????????????mHeight =360;
? ? ? ? ? ? ? ????size =CameraManager.getOptimalSize(parameters.getSupportedPreviewSizes(),mWidth,mHeight);
????????LogUtils.i("fangzhi","低端機(jī)相機(jī)尺寸二次適配");
????????}
????????????????mWidth =size.width;
????????????????mHeight =size.height;
????????}
????? LogUtils.e("fangzhi","mWH : " +mWidth +" : " +mHeight);
????????parameters.setPreviewSize(mWidth,mHeight);
????????mCamera.setParameters(parameters);
????????mCamera.setPreviewTexture(mTextureView.getSurfaceTexture());
????????mCamera.startPreview();
????????}catch (Exception e) {
????????e.printStackTrace();
????????LogUtils.e("fangzhi","err : " + e.getMessage());
????}
}
2.2? 實(shí)現(xiàn)Camera.PreviewCallback 接口,重寫onPreviewFrame()方法
@Override
public void onPreviewFrame(byte[] data,Camera camera) {
????????if (avcEncoder ==null) {
????????????/ /Log.e("fangzhi", "avcEncoder? == null " + data.length);
? ? ? ? ????return;
????????}
????????if (avcEncoder.nv21Queue.size() >=10) {
????????????avcEncoder.nv21Queue.poll();
????????}
????????avcEncoder.nv21Queue.add(data);
}