Browse Source

修复获取h264数据流

main v1.05
jiangdongguo 7 years ago
parent
commit
a411918d28
  1. 28
      app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
  2. 98
      libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaEncoder.java
  3. 3
      libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaMuxerWrapper.java
  4. 5
      libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoEncoder.java

28
app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java

@ -160,13 +160,6 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
showShortMsg("录制异常,摄像头未开启");
return;
}
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+File.separator+System.currentTimeMillis()+".txt");
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(! mUSBManager.isRecording()){
String videoPath = USBCameraManager.ROOT_PATH+System.currentTimeMillis()
@ -174,32 +167,13 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
mUSBManager.startRecording(videoPath, new AbstractUVCCameraHandler.OnEncodeResultListener() {
@Override
public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) {
String tip = null;
if(data == null){
tip = "data = null";
}else{
tip = "大小"+data.length+ "类型"+type + ";";
}
try {
if(fos != null){
fos.write(tip.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
mBtnRecord.setText("正在录制");
} else {
mUSBManager.stopRecording();
try {
if(fos != null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
mBtnRecord.setText("开始录制");
}
break;

98
libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaEncoder.java

@ -25,8 +25,14 @@ package com.serenegiant.usb.encoder;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
@ -361,6 +367,11 @@ public abstract class MediaEncoder implements Runnable {
}
}
byte[] mPpsSps = new byte[0];
byte[] h264 = new byte[640 * 480 * 3 / 2];
ByteBuffer mBuffer = ByteBuffer.allocate(10240);
long timeStamp = System.currentTimeMillis();
/**
* drain encoded data and write them to muxer
*/
@ -375,9 +386,7 @@ public abstract class MediaEncoder implements Runnable {
Log.w(TAG, "muxer is unexpectedly null");
return;
}
byte[] mPpsSps = new byte[0];
byte[] h264 = new byte[640 * 480];
ByteBuffer mBuffer = ByteBuffer.allocate(10240);
LOOP: while (mIsCapturing) {
// get encoded data with maximum timeout duration of TIMEOUT_USEC(=10[msec])
@ -447,57 +456,58 @@ LOOP: while (mIsCapturing) {
muxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
prevOutputPTSUs = mBufferInfo.presentationTimeUs;
// 推流,获取h.264数据流
// if(mListener != null){
// byte[] temp = new byte[mBufferInfo.size];
// encodedData.get(temp);
// mListener.onEncodeResult(temp, 0,mBufferInfo.size, mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
// }
// 推流,获取h.264数据流
// 根据mBufferInfo.size来判断音视频
// > 1000,视频;< 1000,音频
if(mBufferInfo.size > 1000){
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;
synchronized (this){
if(mBufferInfo.size > 1000) {
int type = encodedData.get(4) & 0x07;
if(type == 7 || type == 8) {
byte[] outData = new byte[mBufferInfo.size];
encodedData.get(outData);
mPpsSps = outData;
}else if(type == 5) {
System.arraycopy(mPpsSps,0,h264,0,mPpsSps.length);
if(mBufferInfo.size > h264.length) {
continue;
}
encodedData.get(h264,mPpsSps.length,mBufferInfo.size);
if(mListener != null) {
mListener.onEncodeResult(h264, 0,mPpsSps.length + mBufferInfo.size,
mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
}
} else {
mPpsSps = new byte[0];
if(mBufferInfo.size > h264.length){
continue ;
}
encodedData.get(h264,0,mBufferInfo.size);
if(System.currentTimeMillis() - timeStamp >= 3000) {
timeStamp = System.currentTimeMillis();
if(Build.VERSION.SDK_INT >= 23) {
Bundle params = new Bundle();
params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
mMediaCodec.setParameters(params);
}
}
if(mListener != null) {
mListener.onEncodeResult(h264, 0,mBufferInfo.size,
mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
}
}
}
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);
}
} else {
encodedData.get(h264, 0, mBufferInfo.size);
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(h264, 0,mBufferInfo.size, mBufferInfo.presentationTimeUs / 1000,TYPE_VIDEO);
mListener.onEncodeResult(mBuffer.array(),0, mBufferInfo.size + 7, mBufferInfo.presentationTimeUs / 1000,TYPE_AUDIO);
}
}
} else {
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);
}
}
}
// return buffer to encoder
mMediaCodec.releaseOutputBuffer(encoderStatus, false);

3
libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaMuxerWrapper.java

@ -1,8 +1,10 @@
package com.serenegiant.usb.encoder;
import android.annotation.TargetApi;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
@ -27,6 +29,7 @@ public class MediaMuxerWrapper {
private boolean mIsStarted;
private MediaEncoder mVideoEncoder, mAudioEncoder;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public MediaMuxerWrapper(String path) throws IOException {
try {
// 保存到自定义路径还是手机默认Movies路径

5
libusbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoEncoder.java

@ -23,10 +23,12 @@
package com.serenegiant.usb.encoder;
import android.annotation.TargetApi;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
@ -82,6 +84,7 @@ public class MediaVideoEncoder extends MediaEncoder implements IVideoEncoder {
return result;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
protected void prepare() throws IOException {
if (DEBUG) Log.i(TAG, "prepare: ");
@ -99,7 +102,7 @@ public class MediaVideoEncoder extends MediaEncoder implements IVideoEncoder {
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // API >= 18
format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate());
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
if (DEBUG) Log.i(TAG, "format: " + format);
mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);

Loading…
Cancel
Save