- 浏览: 223288 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
啊嘞嘞勒:
游戏结束无法显示
自己制作的 java 版 2048游戏 -
VIP庚:
dufangyu1990 写道VIP庚 写 ...
Android 视频通话(一) -
dufangyu1990:
VIP庚 写道dufangyu1990 写 ...
Android 视频通话(一) -
VIP庚:
dufangyu1990 写道VIP庚 写道dufangyu1 ...
Android 视频通话(一) -
dufangyu1990:
VIP庚 写道dufangyu1990 写道VIP庚 写道du ...
Android 视频通话(一)
最近再弄实时视频通话方面,参考了很多资料,自己写了个demo,供大家参考,毕竟网上的资料也不多
先介绍视频的传输,通过H264编码,rtp协议进行传输,后面后github下载地址
一 流程:
1、通过Camera的回调函数,得到实时视频流
2、将得到的视频流通过H264编码
3、将H264编码后的数据打包成rtp包,并发送给对方
4、对方接受rtp包后,对视频流数据进行H264解码
5、将解码后的数据通过自定义view一帧帧的显示出来
二、H264编解码
得到的视频流数据太大,必须进行压缩后才能传输,这儿我才用了H264编码。
偷了个懒,demo中直接将别人的已经生成好的编解码库拿来用(.so文件),注意使用别人的.so文件,Java调用解码库中的类名,包名,方法名一定要与别人的一致,不然的话用不了。正常情况下直接需要通过NDK来生成。
三 RTP协议
这儿 我先简单的介绍一下rtp协议
RTP全名是Real-time Transport Protocol(实时传输协议),且配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务。
rtp协议中定义了时间戳,可以通过这个时间戳来同步音频流和视频流,这样就达到声音和视频的同步,实现视频通话。
有兴趣的盆友可以在网上查一下rtp协议的相关介绍和其包的结构
demo中用的rtp传输时参考spydroid这个开源的视频通话项目,网上也有对spydroid的分析。
核心代码:
rtp发送
rtp接收:
注意:
这儿将视频流通过H264压缩后,可能由于数据过大,这一次的数据要分成几个rtp包发送,send_packetNum就是分包的的个数,sequence为序列号,用来标记这是第几个包,setMarker是用来设置这是不是这次数据的最后一个包。接收端通过sequence,marker、时间戳 来对之次的数据进行重新组装,然后将组装后的数据进行解码显示。
四 原始视频流的获取
在Callback 的onPreviewFrame函数中就能获得原始视频数据流,然后对这个数据流进行压缩,打包,发送
五 视频流的显示
每次收到一帧的数据后,将解码后的数据放入mPixel 中,在刷新视图
这儿只是实现点对点内网之间的视频实时传输,后面我应该还会继续将服务器、语音弄下去,到时再分享
ps:我试过用Java udp服务器作为中转站,将两边的实时数据进行转发,效果也还行。但我还想实现外网中p2p之间的实时视频,用服务器作为中转站,将两边的实时ip和端口号分别转发给双方,这样两边就可以在外网进行点对点的视频,但我试过很多次,这样的udp打洞很难实现,因为服务器得到的客户端的端口号是这次连接的,但当进行p2p连接时,端口号可能又会发生变化。希望有大牛可以指点迷津。
guthub地址:https://github.com/592713711/Android-VideoChat
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
大神能留个联系方式吗?想请教下关于这方面的问题。。。
加我qq吧 592713711
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
大神能留个联系方式吗?想请教下关于这方面的问题。。。
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
首先你要确定 AB双方的网络类型 一般分为锥形和对称形 不同类型的网络都需要不同类型的穿透方法 锥形的比较好办 对称形的话你就行需要对它的传输的端口进行分析
这里可以参考:
http://blog.csdn.net/h_armony/article/details/45167975
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
楼主能不能将FFmpegVideoChat写个简单的说明?如何设置,如何使用。谢谢
你在FFmpegVideoChat 切换到ffmpeg分支 里面有FfmpegServer用来编码的 你可以看看,这个工程你那边很难跑起来 所以你需要把这块抽出来 在onPreviewFrame收到Camera回调的原始数据通过ffmpegServer.sendData(frame)来编码发送 不过这里编译的ffmpeg库可能有点问题
这样的 这个FFmpegVideoChat是我自己工程拉出的分支 服务器是自己的,这里你可以单独的吧FFmpeg抽出来用
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
楼主能不能将FFmpegVideoChat写个简单的说明?如何设置,如何使用。谢谢
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
源码就在上面github地址里~
我说的是c++的源码,就是h264编解码的源码,我nexus 5x 7.0报上面那个错,应该是需要用新版的ndk重新编译so库
demo中的源码没有 不过我编译了ffmpeg的 https://github.com/592713711/FFmpegVideoChat/tree/ffmpeg/ffmpeg
你可以参考下 现在FFmpeg比较主流
先介绍视频的传输,通过H264编码,rtp协议进行传输,后面后github下载地址
一 流程:
1、通过Camera的回调函数,得到实时视频流
2、将得到的视频流通过H264编码
3、将H264编码后的数据打包成rtp包,并发送给对方
4、对方接受rtp包后,对视频流数据进行H264解码
5、将解码后的数据通过自定义view一帧帧的显示出来
二、H264编解码
得到的视频流数据太大,必须进行压缩后才能传输,这儿我才用了H264编码。
偷了个懒,demo中直接将别人的已经生成好的编解码库拿来用(.so文件),注意使用别人的.so文件,Java调用解码库中的类名,包名,方法名一定要与别人的一致,不然的话用不了。正常情况下直接需要通过NDK来生成。
三 RTP协议
这儿 我先简单的介绍一下rtp协议
RTP全名是Real-time Transport Protocol(实时传输协议),且配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务。
rtp协议中定义了时间戳,可以通过这个时间戳来同步音频流和视频流,这样就达到声音和视频的同步,实现视频通话。
有兴趣的盆友可以在网上查一下rtp协议的相关介绍和其包的结构
demo中用的rtp传输时参考spydroid这个开源的视频通话项目,网上也有对spydroid的分析。
核心代码:
rtp发送
//mCamera回调的类 class Callback implements Camera.PreviewCallback { @Override public void onPreviewFrame(byte[] frame, Camera camera) { if (encoder_handle != -1) { //底层函数,返回包的数目,返回包的大小存储在数组packetSize中,返回码流在stream中 send_packetNum = encode.EncoderOneFrame(encoder_handle, -1, frame, send_stream, send_packetSize); Log.d("log", "原始数据大小:" + frame.length + " 转码后数据大小:" + send_stream.length); if (send_packetNum > 0) { //通过RTP协议发送帧 final int[] pos = {0}; //从码流头部开始取 final long timestamp = System.currentTimeMillis(); //设定时间戳 /** * 因为可能传输数据过大 会将一次数据分割成好几段来传输 * 接受方 根据序列号和结束符 来将这些数据拼接成完整数据 */ new Thread(new Runnable() { @Override public void run() { int sequence = 0; //初始化序列号 for (int i = 0; i < send_packetNum; i++) { rtp_send_packet.setPayloadType(2);//定义负载类型,视频为2 rtp_send_packet.setMarker(i == send_packetNum - 1 ? true : false); //是否是最后一个RTP包 rtp_send_packet.setSequenceNumber(sequence++); //序列号依次加1 rtp_send_packet.setTimestamp(timestamp); //时间戳 //Log.d("log", "序列号:" + sequence + " 时间:" + timestamp); rtp_send_packet.setPayloadLength(send_packetSize[i]); //包的长度,packetSize[i]+头文件 //从码流stream的pos处开始复制,从socketBuffer的第12个字节开始粘贴,packetSize为粘贴的长度 System.arraycopy(send_stream, pos[0], socket_send_Buffer, 12, send_packetSize[i]); //把一个包存在socketBuffer中 pos[0] += send_packetSize[i]; //重定义下次开始复制的位置 //rtp_packet.setPayload(socketBuffer, rtp_packet.getLength()); // Log.d("log", "序列号:" + sequence + " bMark:" + rtp_packet.hasMarker() + " packetSize:" + packetSize[i] + " tPayloadType:2" + " timestamp:" + timestamp); try { rtp_socket.send(rtp_send_packet); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } } } }
rtp接收:
/** * 接收rtp数据并解码 线程 */ class DecoderThread extends Thread { public void run() { while (isRunning) { try { rtp_socket.receive(rtp_receive_packet); //接收一个包 } catch (IOException e) { e.printStackTrace(); } int packetSize = rtp_receive_packet.getPayloadLength(); //获取包的大小 if (packetSize <= 0) continue; if (rtp_receive_packet.getPayloadType() != 2) //确认负载类型为2 continue; System.arraycopy(socket_receive_Buffer, 12, buffer, 0, packetSize); //socketBuffer->buffer int sequence = rtp_receive_packet.getSequenceNumber(); //获取序列号 long timestamp = rtp_receive_packet.getTimestamp(); //获取时间戳 int bMark = rtp_receive_packet.hasMarker() == true ? 1 : 0; //是否是最后一个包 int frmSize = decode.PackH264Frame(decoder_handle, buffer, packetSize, bMark, (int) timestamp, sequence, frmbuf); //packer=拼帧器,frmbuf=帧缓存 Log.d("log", "序列号:" + sequence + " bMark:" + bMark + " packetSize:" + packetSize + " PayloadType:" + rtp_receive_packet.getPayloadType() + " timestamp:" + timestamp + " frmSize:" + frmSize); if (frmSize <= 0) continue; decode.DecoderNal(frmbuf, frmSize, view.mPixel);//解码后的图像存在mPixel中 //Log.d("log","序列号:"+sequence+" 包大小:"+packetSize+" 时间:"+timestamp+" frmbuf[30]:"+frmbuf[30]); view.postInvalidate(); } //关闭 if (decoder_handle != 0) { decode.DestroyH264Packer(decoder_handle); decoder_handle = 0; } if (rtp_socket != null) { rtp_socket.close(); rtp_socket = null; } decode.DestoryDecoder(); } }
注意:
这儿将视频流通过H264压缩后,可能由于数据过大,这一次的数据要分成几个rtp包发送,send_packetNum就是分包的的个数,sequence为序列号,用来标记这是第几个包,setMarker是用来设置这是不是这次数据的最后一个包。接收端通过sequence,marker、时间戳 来对之次的数据进行重新组装,然后将组装后的数据进行解码显示。
四 原始视频流的获取
if (mCamera == null) { //摄像头设置,预览视频 mCamera = Camera.open(1); //实例化摄像头类对象 0为后置 1为前置 Camera.Parameters p = mCamera.getParameters(); //将摄像头参数传入p中 p.setFlashMode("off"); p.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); p.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO); p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //p.setPreviewFormat(PixelFormat.YCbCr_420_SP); //设置预览视频的格式 p.setPreviewFormat(ImageFormat.NV21); p.setPreviewSize(352, 288); //设置预览视频的尺寸,CIF格式352×288 //p.setPreviewSize(800, 600); p.setPreviewFrameRate(15); //设置预览的帧率,15帧/秒 mCamera.setParameters(p); //设置参数 byte[] rawBuf = new byte[1400]; mCamera.addCallbackBuffer(rawBuf); mCamera.setDisplayOrientation(90); //视频旋转90度 try { mCamera.setPreviewDisplay(holder); //预览的视频显示到指定窗口 } catch (IOException e) { e.printStackTrace(); } mCamera.startPreview(); //开始预览 //获取帧 //预览的回调函数在开始预览的时候以中断方式被调用,每秒调用15次,回调函数在预览的同时调出正在播放的帧 Callback a = new Callback(); mCamera.setPreviewCallback(a); } } //mCamera回调的类 class Callback implements Camera.PreviewCallback { @Override public void onPreviewFrame(byte[] frame, Camera camera) { }
在Callback 的onPreviewFrame函数中就能获得原始视频数据流,然后对这个数据流进行压缩,打包,发送
五 视频流的显示
/** * 显示H264解码后视频 一帧一帧的按图片显示 */ public class VideoPlayView extends View { public int width = 352; public int height = 288; public byte[] mPixel = new byte[width * height * 2]; public ByteBuffer buffer = ByteBuffer.wrap(mPixel); public Bitmap VideoBit = Bitmap.createBitmap(width, height, Config.RGB_565); private Matrix matrix = null; public Bitmap VideoBit2; private RectF rectF; public VideoPlayView(Context context, AttributeSet attrs) { super(context, attrs); matrix = new Matrix(); DisplayMetrics dm = getResources().getDisplayMetrics(); int W = dm.widthPixels; int H = dm.heightPixels; rectF = new RectF(0, 0, W, H); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); buffer.rewind(); VideoBit.copyPixelsFromBuffer(buffer); setAngle(); //canvas.drawBitmap(adjustPhotoRotation(VideoBit,90), 0, 0, null); // //Bitmap b = BitmapFactory.decodeByteArray(mPixel, 0, mPixel.length); canvas.drawBitmap(VideoBit2, null, rectF, null); } // 设置旋转比例 private void setAngle() { matrix.reset(); matrix.setRotate(-90); VideoBit2 = Bitmap.createBitmap(VideoBit, 0, 0, VideoBit.getWidth(),VideoBit.getHeight(), matrix, true); } private Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) { Matrix m = new Matrix(); m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2); float targetX, targetY; if (orientationDegree == 90) { targetX = bm.getHeight(); targetY = 0; } else { targetX = bm.getHeight(); targetY = bm.getWidth(); } final float[] values = new float[9]; m.getValues(values); float x1 = values[Matrix.MTRANS_X]; float y1 = values[Matrix.MTRANS_Y]; m.postTranslate(targetX - x1, targetY - y1); Bitmap bm1 = Bitmap.createBitmap(bm.getHeight(), bm.getWidth(), Config.ARGB_8888); Paint paint = new Paint(); Canvas canvas = new Canvas(bm1); canvas.drawBitmap(bm, m, paint); return bm1; } }
每次收到一帧的数据后,将解码后的数据放入mPixel 中,在刷新视图
decode.DecoderNal(frmbuf, frmSize, view.mPixel);//解码后的图像存在mPixel中 view.postInvalidate();
这儿只是实现点对点内网之间的视频实时传输,后面我应该还会继续将服务器、语音弄下去,到时再分享
ps:我试过用Java udp服务器作为中转站,将两边的实时数据进行转发,效果也还行。但我还想实现外网中p2p之间的实时视频,用服务器作为中转站,将两边的实时ip和端口号分别转发给双方,这样两边就可以在外网进行点对点的视频,但我试过很多次,这样的udp打洞很难实现,因为服务器得到的客户端的端口号是这次连接的,但当进行p2p连接时,端口号可能又会发生变化。希望有大牛可以指点迷津。
guthub地址:https://github.com/592713711/Android-VideoChat
评论
28 楼
VIP庚
2017-10-19
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
大神能留个联系方式吗?想请教下关于这方面的问题。。。
加我qq吧 592713711
27 楼
dufangyu1990
2017-10-19
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
大神能留个联系方式吗?想请教下关于这方面的问题。。。
26 楼
VIP庚
2017-10-18
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
你所说的打洞是指局域网通信 还公网点对点通信? rtp_socket.receive(rtp_receive_packet这个方法是接受对方传过来的rtp数据 你要保证对方要发送数据 且你可以收到
25 楼
dufangyu1990
2017-10-17
VIP庚 写道
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
我这边已经打洞成功了,互相能发数据,现在想直接连接对方,传输音视频,我看到ffmpeg
分支里面的ffmpegServer.sendData(frame)是连接服务器端口的,我把serverAddress改成另一个手机的ip和端口,发现解码就一直停留在 rtp_socket.receive(rtp_receive_packet); 不会向下执行了,,这样改行吗?
24 楼
VIP庚
2017-10-17
dufangyu1990 写道
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
1、传入的端口是远程服务器的端口 用来建立socket连接的
2、这个问题 你要断点下 看看为什么只循环一次
3、退出时回 断开socket 这个应该不影响
23 楼
dufangyu1990
2017-10-17
大神,你的ffmpegServer.sendData(frame)是发送到服务器,然后通过服务器转发,客户端再解码吗?我把serverAddress换成手机的ip,发现不会进入解码流程,,这是正常的吗?
22 楼
dufangyu1990
2017-10-16
VIP庚 写道
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
大神,我在代码里面加了surfaceview后能正常显示视频了,现在关于音频有几个问题,麻烦大神解答下,1.audioServer初始化的时候,需要传入ip和端口,这个ip我传入的是手机的ip,端口我随便写了一个,可以吗?这个端口号和视频的端口号应该是不一样的吧?
2.音频调用startRecording()之后EncodeThreadl里面的while循环只打印了一次,按返回键退出的时候DecoderThread打印接收音频数据为0,
3.按返回键退出的时候,总会报一个异常java.net.SocketException: Socket is closed,
发现FfmpegServer和audioServer都会报这个,,请问有什么好的方法解决吗?
麻烦大神了
21 楼
VIP庚
2017-10-14
dufangyu1990 写道
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
你好 最近工作太忙了 没时间整理...
onPreviewFrame 这个方法是系统摄像头 api回调的 和我这边应该没什么关系
20 楼
dufangyu1990
2017-10-13
大神,我把ffmpeg分支里面获取视频流数据的放到我demo里面,发现onPreviewFrame不会被调用,请问你那边正常吗?
19 楼
dufangyu1990
2017-09-20
大神,有完整的demo吗?看你好久没更新了
18 楼
VIP庚
2017-05-26
dufangyu1990 写道
楼主,我最近在做udp穿透的,用的是Netty4这个网络框架,发现我这边能接收另外一个客户端B发过来的信息,但是B却接收不到我发过去的,不知道你有碰到过这个问题吗?
首先你要确定 AB双方的网络类型 一般分为锥形和对称形 不同类型的网络都需要不同类型的穿透方法 锥形的比较好办 对称形的话你就行需要对它的传输的端口进行分析
这里可以参考:
http://blog.csdn.net/h_armony/article/details/45167975
17 楼
dufangyu1990
2017-05-26
楼主,我最近在做udp穿透的,用的是Netty4这个网络框架,发现我这边能接收另外一个客户端B发过来的信息,但是B却接收不到我发过去的,不知道你有碰到过这个问题吗?
16 楼
VIP庚
2017-05-25
marklxx5000 写道
VIP庚 写道
dufangyu1990 写道
大神,还在弄这块吗?如果想加入音频应该怎么加,
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
楼主能不能将FFmpegVideoChat写个简单的说明?如何设置,如何使用。谢谢
你在FFmpegVideoChat 切换到ffmpeg分支 里面有FfmpegServer用来编码的 你可以看看,这个工程你那边很难跑起来 所以你需要把这块抽出来 在onPreviewFrame收到Camera回调的原始数据通过ffmpegServer.sendData(frame)来编码发送 不过这里编译的ffmpeg库可能有点问题
15 楼
VIP庚
2017-05-25
marklxx5000 写道
请问楼主,我试了你的FFmpegVideoChat这个工程,怎么总提示“登陆失败,请检查网络”??是需要设置什么服务器吗?还是要设置什么?
请楼主看到时回复一下,已磨索几天了,怎么改也不行?
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what== HandlerUtil.REQUEST_ERROR){
//登陆失败
Toast.makeText(LoginActivity.this, "登陆失败,请检查网络", Toast.LENGTH_SHORT).show();
btnMorph.unblockTouch();
morphToSquare(btnMorph, integer(R.integer.mb_animation), "重新登陆", color(R.color.theme));
}
}
请楼主看到时回复一下,已磨索几天了,怎么改也不行?
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what== HandlerUtil.REQUEST_ERROR){
//登陆失败
Toast.makeText(LoginActivity.this, "登陆失败,请检查网络", Toast.LENGTH_SHORT).show();
btnMorph.unblockTouch();
morphToSquare(btnMorph, integer(R.integer.mb_animation), "重新登陆", color(R.color.theme));
}
}
这样的 这个FFmpegVideoChat是我自己工程拉出的分支 服务器是自己的,这里你可以单独的吧FFmpeg抽出来用
14 楼
marklxx5000
2017-05-24
VIP庚 写道
dufangyu1990 写道
大神,还在弄这块吗?如果想加入音频应该怎么加,
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
楼主能不能将FFmpegVideoChat写个简单的说明?如何设置,如何使用。谢谢
13 楼
marklxx5000
2017-05-24
请问楼主,我试了你的FFmpegVideoChat这个工程,怎么总提示“登陆失败,请检查网络”??是需要设置什么服务器吗?还是要设置什么?
请楼主看到时回复一下,已磨索几天了,怎么改也不行?
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what== HandlerUtil.REQUEST_ERROR){
//登陆失败
Toast.makeText(LoginActivity.this, "登陆失败,请检查网络", Toast.LENGTH_SHORT).show();
btnMorph.unblockTouch();
morphToSquare(btnMorph, integer(R.integer.mb_animation), "重新登陆", color(R.color.theme));
}
}
请楼主看到时回复一下,已磨索几天了,怎么改也不行?
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what== HandlerUtil.REQUEST_ERROR){
//登陆失败
Toast.makeText(LoginActivity.this, "登陆失败,请检查网络", Toast.LENGTH_SHORT).show();
btnMorph.unblockTouch();
morphToSquare(btnMorph, integer(R.integer.mb_animation), "重新登陆", color(R.color.theme));
}
}
12 楼
VIP庚
2017-05-19
dufangyu1990 写道
大神,还在弄这块吗?如果想加入音频应该怎么加,
6 7月份我会上传完整的Demo 加音频和视频是一样的 将音频流数据用编码器编码码(可以用iLBC)然后通过RTP包装发出 这里要注意的的是 要和 视频流进行同步 可以通过视频流和音频流RTP包中的时间戳进行比较
11 楼
dufangyu1990
2017-05-18
大神,还在弄这块吗?如果想加入音频应该怎么加,
10 楼
xiazecheng
2017-04-15
好的,谢谢
9 楼
VIP庚
2017-03-21
xiazecheng 写道
VIP庚 写道
xiazecheng 写道
你好,android7.0.1报这个错
java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.nercms-1/lib/arm/libVideoEncoder.so: has text relocations
我查了一下说是要重新编译jni的库,方便把源码给我一下吗?
java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.nercms-1/lib/arm/libVideoEncoder.so: has text relocations
我查了一下说是要重新编译jni的库,方便把源码给我一下吗?
源码就在上面github地址里~
我说的是c++的源码,就是h264编解码的源码,我nexus 5x 7.0报上面那个错,应该是需要用新版的ndk重新编译so库
demo中的源码没有 不过我编译了ffmpeg的 https://github.com/592713711/FFmpegVideoChat/tree/ffmpeg/ffmpeg
你可以参考下 现在FFmpeg比较主流
相关推荐
本篇将深入解析基于腾讯云视频SDK的Android视频通话demo,帮助你理解和掌握其中的关键知识点。 首先,我们需要了解的是**腾讯云视频SDK**。这是一个强大的多媒体通讯解决方案,提供了包括音视频通话、直播、录制等...
在Android平台上实现视频通话功能,通常涉及到多个技术层面和组件的...通过研究和理解这段代码,可以深入掌握Android视频通话的相关技术,并为自己的项目构建类似功能。建议开发者下载并根据自身需求进行定制和扩展。
在Android平台上实现视频通话功能是一项复杂而重要的任务,涉及到多媒体处理、网络通信、实时传输等多个技术领域。这里我们主要探讨的是一个基于Android的视频通话源码项目,它包含两个示例,可以帮助开发者深入理解...
在Android平台上实现SIP(Session Initiation Protocol)视频通话是一项技术含量较高的任务,涉及到网络通信、多媒体处理以及用户界面设计等多个方面。SIP是一种应用层的控制协议,用于创建、修改和终止多媒体通信...
在Android平台上实现视频通话及录音功能,涉及到多个技术层面,包括多媒体处理、网络通信、权限管理以及可能的底层系统修改。以下将详细讲解这些关键知识点: 1. **多媒体处理**: - 视频捕获:Android提供了...
【标题】"Android语音视频通话源码"是一个与Android平台上的语音和视频通信技术相关的项目。这个压缩包可能包含了实现这一功能的完整源代码,帮助开发者理解和构建自己的语音和视频通话应用。 【描述】"android语音...
在Android平台上实现音视频通话功能是一项复杂而关键的技术任务,涉及到多媒体处理、网络通信和用户界面等多个方面。本文将深入探讨如何在Android上构建这样的应用,主要基于标题和描述提供的"Android音视频通话例子...
在Android平台上进行视频通话和会议应用的开发是一项技术性很强的工作,涉及到多个核心组件和技术的协同工作。"最新的支持视频通话视频会议的android源码"为开发者提供了一个宝贵的参考资料,帮助理解和实现这样的...
android基于linphone实现视频通话小结
android语音视频通话
总之,实现基于Google WebRTC的Android视频通话涉及WebRTC库的集成、`PeerConnection`的创建与管理、WebSocket通信、信令处理、权限申请等多个环节。每个环节都需要细致的编程和调试,才能为用户提供流畅、稳定的...
android 视频通话 实例源码,采用网易云信sdk开发,开发环境idea.
在Android视频通话中,SIP用于建立和管理视频通话的连接,包括呼叫的发起、接收、挂断以及媒体流的传输控制。 2. miniSipServer:这是一款开源的SIP服务器软件,用于处理SIP协议的注册、呼叫、会话等操作。开发者在...
本项目“Android应用源码之sipdroid语音及视频通话”是一个基于Android的开源应用程序,它为开发者提供了实现VoIP(Voice over Internet Protocol)服务的示例,即通过互联网进行语音和视频通信。这个项目对于那些...
【视频通话 语音聊天源码】是针对移动设备开发的一款通信应用的核心技术,主要用于实现类似微信的实时音视频交流功能。在Android平台上,这样的源码是开发者构建自己的即时通讯(IM)应用程序的基础,它涵盖了从音频...
在android平台上实现了视频通话功能,利用ffmpeg编解码功能,可现实清晰的图像
在安卓(Android)平台上,开发语音和视频通话应用是一个复杂而关键的任务,涉及到多个系统层级的交互和技术。SipDroid项目就是一个开源的解决方案,它允许用户通过SIP(Session Initiation Protocol)协议进行VoIP...
SipDroid是一款开源的Android应用,主要用于实现VoIP(Voice over Internet Protocol)和视频通话功能。它基于SIP(Session Initiation Protocol)协议,这是一种用于控制多媒体通信会话(如语音和视频通话)的标准...
在安卓平台上实现音视频通话是一项复杂的技术任务,通常涉及到网络通信、音视频编码解码、多线程处理等多个方面。然而,通过使用特定的音视频通信SDK,开发者可以简化这一过程,只需调用相应的API就能实现功能。在这...