|
1、直播流程整体流程
1.1 数据采集(通常是摄像头和录屏)
1.2 编码,也叫视频压缩(采用H264编解码协议,格式AVC),H265压缩比例更高,自行选择,使用的MediaCodec,Android原生api
1.3 传输,使用的是Netty网络通讯协议,基于socket封装的非常好网络框架,数据传输序列化用的protobuf(主要用与Android和ios跨平台传输byte[]数据,如果不涉及跨平台,使用Netty即可)
1.4 解码 网络传递过来的byte数据流,解析出视频数据流,由MediaCodec解码
1.5 渲染显示,自定义suface,交给MediaCodec渲染即可
2、首选,我们来看第一步,数据采集
2.1 启动相机,此处使用的是camera1,camera2难使用,资料少,不会的还是建议用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","低端机相机尺寸二次适配");
}
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 实现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);
} |
|