源码下载

不愿意看博客,上来就想抄的,尽情开始吧

RtmpPusher.zip

想了解下原理,和大概流程的,请继续往下看

通过本Demo可以学到的知识点

如何选择最合适的摄像头分辨率

安卓摄像头画面采集方向和预览方向的区别

预览画面时,如何正确旋转预览数据

推流画面时,如何正确旋转采集数据

SurfaceView的生命周期

Surface发生改变时(比如横竖屏切换),如何调整预览和推流工作

摄像头切换时,如何调整预览和推流工作

YUV画面旋转和翻转

RTMP和FLV数据包格式

如何将AAC音频数据封装为RTMPPacket

如何将YUV视频数据封装为RTMPPacket

如何通过librtmp推送音视频数据

推流器初始化,开始,暂停,销毁流程如何设计

推流时断线如何重连

整体流程 / PlayActivity

  1. 创建和初始化native接口RtmpPusher
  2. 创建EventListener,用于处理事件回调
  3. 创建AudioRecordHandler,用于录音和推音频数据
  4. 创建CameraPreviewHandler,用于预览和推视频数据
  5. 将EventListener设置给AudioRecordHandler,CameraPreviewHandler
  6. 调用RtmpPusher.setAudioEncodeInfo通知native层音频参数
  7. 调用AudioRecordHandler.setAudioEncodeInfo设置录音时的音频参数
  8. 调用AudioRecordHandler.start开始录音
  9. SurfaceView.onCreate触发时,调用创建CameraPreviewHandler.startPreview启动Camera,调用CameraPreviewHandler.setPreviewDisplay开始预览
  10. SurfaceView.surfaceChanged触发时,调用CameraPreviewHandler.stopPreview停止旧的Camera,再重启新的Camera和预览
  11. SurfaceView.surfaceDestroyed触发时,调用CameraPreviewHandler.stopPreview停止Camera
  12. 屏幕方向发生变化时,调用CameraPreviewHandler.setPreviewOrientation来刷新预览方向
  13. Activity.onDestroy触发时,调用创建AudioRecordHandler.stop停止录音,调用CameraPreviewHandler.stopPreview停止Camera

录音流程 / AudioRecordHandler

  1. AudioRecordHandler.setAudioEncodeInfo,设置录音参数,采样率,通道数,单次解码样本数
  2. AudioRecordHandler.start,创建AudioRecord,用于录音
  3. AudioRecord.read,创建线程,循环从AudioRecord读取录制数据,并转交给EventListener处理
  4. AudioRecordHandler.stop,停止录音线程,同时销毁AudioRecord,录音结束

视频采集流程 / CameraPreviewHandler

  1. CameraPreviewHandler.startPreview,开始预览
  2. – Camera.setParameters,设置摄像头采集和预览参数
  3. – 调用EventListener.onVideoParamChange,通知native层视频参数改变
  4. – 调用Camera.setPreviewCallback,监听预览数据
  5. – 调用Camera.startPreview,启动摄像头预览
  6. – 调用CameraPreviewHandler.setPreviewOrientation,设置预览图像显示方向
  7. CameraPreviewHandler.setPreviewDisplay,设置用于显示预览图像的Surface
  8. Camera.PreviewCallback回调执行,将帧数据转交给EventListener处理
  9. EventListener将视频数据推给RtmpPusher
  10. CameraPreviewHandler.switchCamera,切换摄像头
  11. – 根据Camera的FaceInfo,切换新的Camera
  12. – 调用EventListener.onCameraSwitch,重启摄像头预览
  13. Activity方向改变,重启摄像头预览,重新设置预览方向
  14. CameraPreviewHandler.stopPreview,停止预览,并释放Camera

RTMP推流流程 / RtmpPusher

  1. 调用RtmpPusher.initialize,初始化AudioChannel,VideoChannel,PacketQueue
  2. 调用AudioChannel.setAudioEncodeInfo,设置音频参数
  3. – 调用libaac.faacEncOpen,创建AAC编码器
  4. – 调用libaac.faacEncSetConfiguration,设置AAC编码器参数
  5. 调用VideoChannel.setVideoEncodeInfo,设置视频参数
  6. – 调用libx264.x264_param_default_preset和libx264.x264_param_apply_profile,创建H264编码配置
  7. – 调用libx264.x264_encoder_open,创建H264编码器
  8. – 调用libx264.x264_picture_alloc,分配一个H264编码输出缓存区
  9. 调用RtmpPusher.prepare,设置URL,连接服务器
  10. – 调用librtmp.RTMP_Alloc,创建RTMP对象
  11. – 调用librtmp.RTMP_Init,初始化RTMP对象
  12. – 调用librtmp.RTMP_SetupURL,设置RTMP地址
  13. – 配置rtmp.Link.timeout,设置RTMP超时时间
  14. – 调用librtmp.RTMP_EnableWrite,设置RTMP为推流模式,另一个模式是取流模式
  15. – 调用librtmp.RTMP_Connect,连接RTMP服务器
  16. – 调用librtmp.RTMP_ConnectStream,连接RTMP流
  17. – 调用librtmp.RTMP_GetTime,记录开始的时间戳
  18. – 创建push线程
  19. 调用libaac.faacEncGetDecoderSpecificInfo,创建AudioSpecificConfig,封装为RTMPPacket,作为首个数据包推送给服务器
  20. push线程不断从PacketQueue中取出RTMPPacket,推送给RTMP服务器
  21. 调用RtmpPusher.pushAudioFrame,向native层推送PCM音频数据
  22. – 调用libaac.faacEncEncode,将PCM编码为AAC裸数据,再封装为RTMPPacket,放入PacketQueue
  23. 调用RtmpPusher.pushVideoFrame,向native层推送NV21视频数据
  24. – 将NV21字节,转换为I420字节,拷贝到输出缓存区
  25. – 调用libx264.x264_encoder_encode,将I420编码为H264
  26. – 将H264封装为RTMPPacket,放入PacketQueue
  27. – SPS和PPS帧封装为一个Packet,其它Slice帧封装为一个Packet
  28. 调用RtmpPusher.pause,暂停PacketQueue推流工作
  29. 调用RtmpPusher.resume,恢复PacketQueue推流工作
  30. 调用RtmpPusher.release
  31. – 停止PacketQueue,结束push线程,释放RTMP对象

摄像头预览角度,和推流画面旋转角度的控制方法