有大神研究Android APP连接UVC摄像头的吗,怎么获取提取使用视频流啊
我已经能预览了,依赖库里好像有视频流采集,我不太懂这块,有人可以帮我看看嘛
@SuppressWarnings("deprecation")
protected void drain() {
if (mMediaCodec == null)
return;
ByteBuffer[] encoderOutputBuffers = mMediaCodec.getOutputBuffers();
int encoderStatus, count = 0;
final MediaMuxerWrapper muxer = mWeakMuxer.get();
if (muxer == null) {
Log.w(TAG, "muxer is unexpectedly null");
return;
}
byte[] mPpsSps = new byte[0];
byte[] h264 = new byte[640 * 480];
while (mIsCapturing) {
encoderStatus = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// 等待 TIMEOUT_USEC x 5 = 50毫秒
// 如果还没有数据,终止循环
if (!mIsEOS) {
if (++count > 5)
break;
}
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
encoderOutputBuffers = mMediaCodec.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
if (mMuxerStarted) {
throw new RuntimeException("format changed twice");
}
final MediaFormat format = mMediaCodec.getOutputFormat();
mTrackIndex = muxer.addTrack(format);
mMuxerStarted = true;
if (!muxer.start()) {
synchronized (muxer) {
while (!muxer.isStarted())
try {
muxer.wait(100);
} catch (final InterruptedException e) {
break;
}
}
}
} else if (encoderStatus < 0) {
if (DEBUG) Log.w(TAG, "drain:unexpected result from encoder#dequeueOutputBuffer: " + encoderStatus);
} else {
ByteBuffer encodedData;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
encodedData = mMediaCodec.getOutputBuffer(encoderStatus);
} else {
encodedData = encoderOutputBuffers[encoderStatus];
}
encodedData.position(mBufferInfo.offset);
encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
// final ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
}
// BUFFER_FLAG_CODEC_CONFIG标志
// BufferInfo清零
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
if (DEBUG) Log.d(TAG, "drain:BUFFER_FLAG_CODEC_CONFIG");
mBufferInfo.size = 0;
}
// BUFFER_FLAG_END_OF_STREAM标志
// 流结束,终止循环
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
mMuxerStarted = mIsCapturing = false;
break;
}
// 有效编码数据流
if (mBufferInfo.size != 0) {
count = 0;
if (!mMuxerStarted) {
throw new RuntimeException("drain:muxer hasn't started");
}
// 写入音频流或视频流到混合器
mBufferInfo.presentationTimeUs = getPTSUs();
muxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
prevOutputPTSUs = mBufferInfo.presentationTimeUs;
// 推流,获取h.264数据流
// mTrackIndex=0 视频;mTrackIndex=1 音频
if(mTrackIndex == 0) {
encodedData.position(mBufferInfo.offset);
encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
boolean sync = false;
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {// sps
sync = (mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
if (!sync) {
byte[] temp = new byte[mBufferInfo.size];
encodedData.get(temp);
mPpsSps = temp;
mMediaCodec.releaseOutputBuffer(encoderStatus, false);
continue;
} else {
mPpsSps = new byte[0];
}
}
sync |= (mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
int len = mPpsSps.length + mBufferInfo.size;
if (len > h264.length) {
h264 = new byte[len];
}
if (sync)
{
System.arraycopy(mPpsSps, 0, h264, 0, mPpsSps.length);
encodedData.get(h264, mPpsSps.length, mBufferInfo.size);
if(mListener != null)
{
mListener.onEncodeResult(h264, 0,mPpsSps.length + mBufferInfo.size,
mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
}
// 保存数据流到文件
FileUtils.putFileStream(h264, 0,mPpsSps.length + mBufferInfo.size);
}
else
{
encodedData.get(h264, 0, mBufferInfo.size);
if(mListener != null)
{
mListener.onEncodeResult(h264, 0,mBufferInfo.size,
mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
}
FileUtils.putFileStream(h264, 0,mBufferInfo.size);
}
} else if(mTrackIndex == 1){
mBuffer.clear();
encodedData.get(mBuffer.array(), 7, mBufferInfo.size);
encodedData.clear();
mBuffer.position(7 + mBufferInfo.size);
addADTStoPacket(mBuffer.array(), mBufferInfo.size + 7);
mBuffer.flip();
if(mListener != null){
mListener.onEncodeResult(mBuffer.array(),0, mBufferInfo.size + 7,
mBufferInfo.presentationTimeUs / 1000,TYPE_AUDIO);
}
}
}
// 释放输出缓存,将其还给编码器
mMediaCodec.releaseOutputBuffer(encoderStatus, false);
}
}
}
这是UVC调用的库里面的一段