优化短视频时间戳的控制

serial
Matthew 1 year ago
parent 109f690a06
commit 6e52602807

@ -69,7 +69,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
private int mCameraId;
private long mVideoId = 0;
private int mDuration = 0;
private long mDuration = 0;
private int mOrientation = -1;
@ -84,10 +84,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
private Paint mPaint;
private Paint mPaintStroker;
private List<Bitmap> mBitmaps = new ArrayList<>();
private GlWatermarkFilter mOSDFilter = null;
private Object mBitmapLocker = new Object();
private SimpleDateFormat mDateFormater;
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
@ -127,71 +124,45 @@ public class Camera2VideoActivity extends AppCompatActivity {
private Handler mHandler = null;
private class TimerRunner implements Runnable {
private Bitmap mBitmap;
TimerRunner(Bitmap bm) {
mBitmap = bm;
}
private Thread mOsdThread = new Thread(new Runnable() {
@Override
public void run() {
Bitmap oldBm = null;
if (mBitmap != null) {
oldBm = mOSDFilter.updateBitmap(mBitmap);
}
if (oldBm != null) {
synchronized (mBitmapLocker) {
mBitmaps.add(oldBm);
}
}
try {
long ts = System.currentTimeMillis();
Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
Bitmap oldBm = null;
Canvas canvas = new Canvas(bm);
long ts = System.currentTimeMillis();
long ms = ts % 1000;
long zeroTs = ts - (ts % 1000);
long nextTs = zeroTs + 1000;
Log.d("OSD", "Cur TS=" + Long.toString(ts / 1000) + " Timer=" + Long.toString(1000 - ms));
while (true) {
try {
if (nextTs > ts) {
Log.i("OSD", "Sleep " + Long.toString(nextTs - ts));
Thread.sleep(nextTs - ts);
}
} catch (InterruptedException ex){
break;
} catch(Exception ex){
}
Message msg = Message.obtain();
msg.what = 1;
msg.obj = new Long(ts - ms + 1000);
mOsdHandler.sendMessage(msg);
}
}
canvas.setBitmap(bm);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
updateOSD(bm, nextTs);
private Handler mOsdHandler;
private Thread mOsdThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mOsdHandler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
if (msg.what == 1) {
Long targetTs = (Long)msg.obj;
long ts = System.currentTimeMillis();
if (ts > targetTs.longValue()) {
return;
}
Bitmap bm = null;
synchronized (mBitmapLocker) {
if (!mBitmaps.isEmpty()) {
bm = mBitmaps.remove(0);
}
}
if (bm != null) {
updateOSD(bm, targetTs.longValue());
oldBm = mOSDFilter.updateBitmap(bm);
bm = oldBm;
TimerRunner runner = new TimerRunner(bm);
mHandler.postDelayed(runner, targetTs.longValue() - ts);
}
} else if (msg.what == 0) {
Looper.myLooper().quitSafely();
ts = System.currentTimeMillis();
zeroTs = ts - (ts % 1000);
if (zeroTs + 1000 > nextTs) {
nextTs = zeroTs + 1000;
}
}
};
Looper.loop();
} catch (Exception ex) {
}
}
});
@ -326,12 +297,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
mHandler = new Handler();
mOsdThread.start();
long ts = 0;
long zeroTs = 0;
Bitmap bm2 = null;
if (!TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop)) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
@ -345,15 +310,12 @@ public class Camera2VideoActivity extends AppCompatActivity {
mPaintStroker.setTextSize(fontSize);
mPaintStroker.setStrokeWidth(1);
bm2 = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
ts = System.currentTimeMillis();
zeroTs = ts - (ts % 1000);
long ts = System.currentTimeMillis();
long zeroTs = ts - (ts % 1000);
initOSD(bm, zeroTs);
mOSDFilter = new GlWatermarkFilter(bm);
@ -361,41 +323,14 @@ public class Camera2VideoActivity extends AppCompatActivity {
mGPUCameraRecorder.setFilter(mOSDFilter);
}
updateOSD(bm2, zeroTs + 1000);
mOsdThread.start();
}
final long prevZeroTs = zeroTs;
final Bitmap finalBm = bm2;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mNextVideoAbsolutePath = getVideoFilePath();
mGPUCameraRecorder.start(mNextVideoAbsolutePath);
if (mOSDFilter != null) {
long ts2 = System.currentTimeMillis();
long zeroTs2 = ts2 - (ts2 % 1000);
if (zeroTs2 > prevZeroTs) {
// Next second
Bitmap oldBm = mOSDFilter.updateBitmap(finalBm);
if (oldBm != null) {
synchronized (mBitmapLocker) {
mBitmaps.add(oldBm);
}
}
Message msg = Message.obtain();
msg.what = 1;
msg.obj = new Long(zeroTs2 + 1000);
// mOsdTs = zeroTs2 + 1000;
mOsdHandler.sendMessage(msg);
} else {
TimerRunner runner = new TimerRunner(finalBm);
mHandler.postDelayed(runner, 1000 - (ts2 - zeroTs2));
}
Log.d("OSD", "Cur TS=" + Long.toString(ts2 / 1000) + " Timer=" + Long.toString(1000 - (ts2 - zeroTs2)));
}
}
}, 0);
@ -416,7 +351,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
private void initOSD(Bitmap bm, long ts) {
Log.d("OSD", "INIT OSD " + Long.toString(ts / 1000));
Log.i("OSD", "INIT OSD " + Long.toString(ts / 1000));
if (mStatusBarHeight == -1) {
mStatusBarHeight = getStatusBarHeight(this);
@ -600,7 +535,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
private void updateOSD(Bitmap bm, long ts) {
Log.d("OSD", "prepareOSD " + Long.toString(ts / 1000));
Log.i("OSD", "prepareOSD " + Long.toString(ts / 1000));
if (mStatusBarHeight == -1) {
mStatusBarHeight = getStatusBarHeight(this);
}
@ -726,27 +661,28 @@ public class Camera2VideoActivity extends AppCompatActivity {
@Override
public void onRecordComplete() {
// mHandler.removeCallbacks(mTimerRunnable);
Message msg = Message.obtain();
msg.what = 0;
mOsdHandler.sendMessage(msg);
}
@Override
public void onRecordStart() {
Log.d("OSD", "Record Start ");
Log.i("OSD", "Record Start ");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.i("OSD", "Record Stop " + Long.toString(mDuration));
mGPUCameraRecorder.stop();
Log.d("OSD", "Record Stop " + Long.toString(mDuration));
int aa = 0;
}
}, 256 + mDuration * 1000);
}, 999 + mDuration * 1000);
}
@Override
public void onError(Exception exception) {
Log.e("GPUCameraRecorder", exception.toString());
mOsdThread.interrupt();
broadcastVideoFile(false, mNextVideoAbsolutePath);
}
@ -757,18 +693,26 @@ public class Camera2VideoActivity extends AppCompatActivity {
@Override
public void onVideoFileReady() {
// exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath);
mOsdThread.interrupt();
broadcastVideoFile(true, mNextVideoAbsolutePath);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Camera2VideoActivity.this.finish();
}
}, 100);
}, 1000);
}
@Override
public void onDurationArrived() {
}
})
.videoSize(mVideoWidth, mVideoHeight)
.cameraSize(mCameraWidth, mCameraHeight)
.cameraId(Integer.toString(mCameraId))
.mute(true)
.duration(mDuration * 1000)
.build();
if (mOSDFilter != null) {

@ -745,10 +745,16 @@ public class Camera2VideoActivityOld extends AppCompatActivity {
}
}, 100);
}
@Override
public void onDurationArrived() {
}
})
.videoSize(mVideoWidth, mVideoHeight)
.cameraSize(mCameraWidth, mCameraHeight)
.cameraId(Integer.toString(mCameraId))
.duration(mDuration * 1000)
.build();
if (mOSDFilter != null) {

@ -16,6 +16,8 @@ public interface CameraRecordListener {
void onCameraThreadFinish();
void onDurationArrived();
/**
* Is called when native codecs finish to write file.
*/

@ -18,7 +18,7 @@ public class GPUCameraRecorder {
private GlPreviewRenderer glPreviewRenderer;
private final CameraRecordListener cameraRecordListener;
private static final String TAG = "GPUCameraRecorder";
private static final String TAG = "OSD";
private boolean started = false;
private CameraHandler cameraHandler = null;
@ -40,6 +40,9 @@ public class GPUCameraRecorder {
private final boolean isLandscapeDevice;
private final int degrees;
private final boolean recordNoFilter;
private final long duration;
private long startTime;
GPUCameraRecorder(
CameraRecordListener cameraRecordListener,
@ -55,7 +58,8 @@ public class GPUCameraRecorder {
final CameraManager cameraManager,
final boolean isLandscapeDevice,
final int degrees,
final boolean recordNoFilter
final boolean recordNoFilter,
final long duration
) {
@ -76,6 +80,7 @@ public class GPUCameraRecorder {
this.isLandscapeDevice = isLandscapeDevice;
this.degrees = degrees;
this.recordNoFilter = recordNoFilter;
this.duration = duration;
// create preview Renderer
if (null == glPreviewRenderer) {
@ -190,7 +195,7 @@ public class GPUCameraRecorder {
@Override
public void onPrepared(final MediaEncoder encoder) {
Log.v("TAG", "onPrepared:encoder=" + encoder);
Log.v(TAG, "onPrepared:encoder=" + encoder);
if (encoder instanceof MediaVideoEncoder) {
videoStopped = false;
if (glPreviewRenderer != null) {
@ -206,7 +211,7 @@ public class GPUCameraRecorder {
@Override
public void onStopped(final MediaEncoder encoder) {
Log.v("TAG", "onStopped:encoder=" + encoder);
Log.v(TAG, "onStopped:encoder=" + encoder);
if (encoder instanceof MediaVideoEncoder) {
videoStopped = true;
if (glPreviewRenderer != null) {
@ -301,7 +306,7 @@ public class GPUCameraRecorder {
} catch (Exception e) {
// RuntimeException is thrown when stop() is called immediately after start().
// In this case the output file is not properly constructed ans should be deleted.
Log.d("TAG", "RuntimeException: stop() is called immediately after start()");
Log.d(TAG, "RuntimeException: stop() is called immediately after start()");
//noinspection ResultOfMethodCallIgnored
notifyOnError(e);
}
@ -330,7 +335,7 @@ public class GPUCameraRecorder {
} catch (Exception e) {
// RuntimeException is thrown when stop() is called immediately after start().
// In this case the output file is not properly constructed ans should be deleted.
Log.d("TAG", "RuntimeException: stop() is called immediately after start()");
Log.d(TAG, "RuntimeException: stop() is called immediately after start()");
}
destroyPreview();

@ -29,6 +29,7 @@ public class GPUCameraRecorderBuilder {
private int cameraWidth = 1280;
private int cameraHeight = 720;
private GlFilter glFilter;
private long duration;
public GPUCameraRecorderBuilder(Activity activity, GLSurfaceView glSurfaceView) {
this.activity = activity;
@ -78,6 +79,11 @@ public class GPUCameraRecorderBuilder {
return this;
}
public GPUCameraRecorderBuilder duration(long d) {
this.duration = d;
return this;
}
public GPUCameraRecorderBuilder recordNoFilter(boolean recordNoFilter) {
this.recordNoFilter = recordNoFilter;
return this;
@ -112,7 +118,8 @@ public class GPUCameraRecorderBuilder {
cameraManager,
isLandscapeDevice,
degrees,
recordNoFilter
recordNoFilter,
duration
);
GPUCameraRecorder.setFilter(glFilter);

@ -15,7 +15,8 @@ import java.io.IOException;
public class MediaVideoEncoder extends MediaEncoder {
private static final String TAG = "MediaVideoEncoder";
// private static final String TAG = "MediaVideoEncoder";
private static final String TAG = "OSD";
private static final String MIME_TYPE = "video/avc";
// parameters for recording

Loading…
Cancel
Save