tuttelikz

FFmpegRecordActivity [vs1]

Jun 11th, 2018
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 60.25 KB | None | 0 0
  1. package com.soialab.askaruly.camera_sensor;
  2.  
  3. import android.Manifest;
  4. import android.app.ProgressDialog;
  5. import android.bluetooth.BluetoothAdapter;
  6. import android.bluetooth.BluetoothDevice;
  7. import android.content.ActivityNotFoundException;
  8. import android.content.BroadcastReceiver;
  9. import android.content.Context;
  10. import android.content.Intent;
  11. import android.content.IntentFilter;
  12. import android.content.pm.PackageManager;
  13. import android.graphics.Color;
  14. import android.graphics.SurfaceTexture;
  15. import android.hardware.Camera;
  16. import android.media.AudioFormat;
  17. import android.media.AudioRecord;
  18. import android.media.MediaRecorder;
  19. import android.net.Uri;
  20. import android.os.AsyncTask;
  21. import android.os.Build;
  22. import android.os.Handler;
  23. import android.support.annotation.NonNull;
  24. import android.support.annotation.RequiresApi;
  25. import android.support.v4.app.ActivityCompat;
  26. import android.support.v4.content.ContextCompat;
  27. import android.support.v7.app.AppCompatActivity;
  28. import android.os.Bundle;
  29. import android.text.TextUtils;
  30. import android.text.method.ScrollingMovementMethod;
  31. import android.util.Log;
  32. import android.view.Menu;
  33. import android.view.MenuInflater;
  34. import android.view.MenuItem;
  35. import android.view.Surface;
  36. import android.view.TextureView;
  37. import android.view.View;
  38. import android.widget.Button;
  39. import android.widget.CompoundButton;
  40. import android.widget.EditText;
  41. import android.widget.GridLayout;
  42. import android.widget.LinearLayout;
  43. import android.widget.RelativeLayout;
  44. import android.widget.ScrollView;
  45. import android.widget.Switch;
  46. import android.widget.TextView;
  47. import android.widget.Toast;
  48. import android.widget.ToggleButton;
  49.  
  50. import com.github.mikephil.charting.charts.LineChart;
  51. import com.github.mikephil.charting.components.Legend;
  52. import com.github.mikephil.charting.components.XAxis;
  53. import com.github.mikephil.charting.components.YAxis;
  54. import com.github.mikephil.charting.data.Entry;
  55. import com.github.mikephil.charting.data.LineData;
  56. import com.github.mikephil.charting.data.LineDataSet;
  57. import com.github.mikephil.charting.utils.ColorTemplate;
  58.  
  59. import org.bytedeco.javacpp.avcodec;
  60. import org.bytedeco.javacpp.avutil;
  61. import org.bytedeco.javacv.FFmpegFrameFilter;
  62. import org.bytedeco.javacv.FFmpegFrameRecorder;
  63. import org.bytedeco.javacv.Frame;
  64. import org.bytedeco.javacv.FrameFilter;
  65. import org.w3c.dom.Text;
  66.  
  67. import java.io.BufferedReader;
  68. import java.io.File;
  69. import java.io.FileOutputStream;
  70. import java.io.FileWriter;
  71. import java.io.IOException;
  72. import java.io.InputStream;
  73. import java.io.InputStreamReader;
  74. import java.nio.ByteBuffer;
  75. import java.nio.ShortBuffer;
  76. import java.nio.charset.Charset;
  77. import java.nio.charset.StandardCharsets;
  78. import java.text.SimpleDateFormat;
  79. import java.util.ArrayList;
  80. import java.util.Date;
  81. import java.util.List;
  82. import java.util.Stack;
  83. import java.util.concurrent.LinkedBlockingQueue;
  84. import java.nio.file.Path;
  85. import java.nio.file.Files;
  86. import de.siegmar.fastcsv.writer.CsvAppender;
  87. import de.siegmar.fastcsv.writer.CsvWriter;
  88. import me.aflak.bluetooth.Bluetooth;
  89.  
  90. import static java.lang.Thread.State.WAITING;
  91.  
  92. public class FFmpegRecordActivity extends AppCompatActivity implements
  93.         TextureView.SurfaceTextureListener, View.OnClickListener, Bluetooth.CommunicationCallback {
  94.  
  95.     private static final String LOG_TAG = FFmpegRecordActivity.class.getSimpleName();
  96.  
  97.     private static final int REQUEST_PERMISSIONS = 1;
  98.  
  99.     private static final int PREFERRED_PREVIEW_WIDTH = 640;
  100.     private static final int PREFERRED_PREVIEW_HEIGHT = 480;
  101.  
  102.     // both in milliseconds
  103.     private static final long MIN_VIDEO_LENGTH = 1 * 1000;
  104.     private static final long MAX_VIDEO_LENGTH = 90 * 1000;
  105.  
  106.     private FixedRatioCroppedTextureView mPreview;
  107.     private Button mBtnResumeOrPause;
  108.     private Button mBtnDone;
  109.     private Button mBtnSwitchCamera;
  110.     private Button mBtnReset;
  111.  
  112.     private int mCameraId;
  113.     private Camera mCamera;
  114.     private FFmpegFrameRecorder mFrameRecorder;
  115.     private VideoRecordThread mVideoRecordThread;
  116.     private AudioRecordThread mAudioRecordThread;
  117.     private volatile boolean mRecording = false;
  118.     private File mVideo;
  119.     private File mText;
  120.     private LinkedBlockingQueue<FrameToRecord> mFrameToRecordQueue;
  121.     private LinkedBlockingQueue<FrameToRecord> mRecycledFrameQueue;
  122.     private int mFrameToRecordCount;
  123.     private int mFrameRecordedCount;
  124.     private long mTotalProcessFrameTime;
  125.     private Stack<RecordFragment> mRecordFragments;
  126.  
  127.  
  128.     private int sampleAudioRateInHz = 44100;
  129.     /* The sides of width and height are based on camera orientation.
  130.     That is, the preview size is the size before it is rotated. */
  131.     private int mPreviewWidth = PREFERRED_PREVIEW_WIDTH;
  132.     private int mPreviewHeight = PREFERRED_PREVIEW_HEIGHT;
  133.     // Output video size
  134.     private int videoWidth = 320;
  135.     private int videoHeight = 240;
  136.     private int frameRate = 30;
  137.     private int frameDepth = Frame.DEPTH_UBYTE;
  138.     private int frameChannels = 2;
  139.  
  140.     // Workaround for https://code.google.com/p/android/issues/detail?id=190966
  141.     private Runnable doAfterAllPermissionsGranted;
  142.  
  143.     ///////////////////////////////////////////////////////////////////////////////////////
  144.     private String name;
  145.     private Bluetooth b;
  146.     private EditText message;
  147.     private Button send;
  148.     private TextView text;
  149.     private ScrollView scrollView;
  150.     private boolean registered=false;
  151.     ///////////////////////////////////////////////////////////////////////////////////////
  152.     private boolean resumeBtnPressed = false;
  153.     private FileWriter writer;
  154.     private CsvWriter csvWriter;
  155.  
  156.     // Sensor display
  157.     private TextView timeinfo;
  158.     private TextView hrinfo;
  159.     private TextView oxinfo;
  160.     private TextView tenoinfo;
  161.     private TextView audioInfo;
  162.     private TextView stretchInfo;
  163.  
  164.     // Accelerometer
  165.     private TextView yawInfo;
  166.     private TextView pitchInfo;
  167.     private TextView rollInfo;
  168.  
  169.     // Int for writing header
  170.     private boolean sensorHeaderCheck = false;
  171.     private int sensorValueIndex = 0;
  172.  
  173.     private float hrTtl = 0;
  174.     private float oxTtl = 0;
  175.     private float tempTtl = 0;
  176.     private float audioTtl = 0;
  177.     private float stretchTtl = 0;
  178.     private float yawTtl = 0;
  179.     private float pitchTtl = 0;
  180.     private float rollTtl = 0;
  181.  
  182.     private int sensValCount = 0;
  183.  
  184.     // Plotting variables
  185.     private RelativeLayout mainLayout;
  186.     private LineChart mChart1;
  187.     //private LineChart mChart2;
  188.  
  189.     private Switch modeSwitch;
  190.  
  191.     //
  192.     RelativeLayout linechartLayout;
  193.     GridLayout sensorsGridLayout;
  194.  
  195.     @Override
  196.     protected void onCreate(Bundle savedInstanceState) {
  197.         super.onCreate(savedInstanceState);
  198.         setContentView(R.layout.activity_ffmpeg_record);
  199.  
  200.         //
  201.         mPreview = (FixedRatioCroppedTextureView) findViewById(R.id.camera_preview);
  202.         mBtnResumeOrPause = (Button) findViewById(R.id.btn_resume_or_pause);
  203.         mBtnDone = (Button) findViewById(R.id.btn_done);
  204.         mBtnSwitchCamera = (Button) findViewById(R.id.btn_switch_camera);
  205.         mBtnReset = (Button) findViewById(R.id.btn_reset);
  206.  
  207.  
  208.  
  209. //        mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
  210.         mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
  211.         setPreviewSize(mPreviewWidth, mPreviewHeight);
  212.         mPreview.setCroppedSizeWeight(videoWidth, videoHeight);
  213.         mPreview.setSurfaceTextureListener(this);
  214.         mBtnResumeOrPause.setOnClickListener(this);
  215.         mBtnDone.setOnClickListener(this);
  216.         mBtnSwitchCamera.setOnClickListener(this);
  217.         mBtnReset.setOnClickListener(this);
  218.  
  219.         // At most buffer 10 Frame
  220.         mFrameToRecordQueue = new LinkedBlockingQueue<>(10);
  221.         // At most recycle 2 Frame
  222.         mRecycledFrameQueue = new LinkedBlockingQueue<>(2);
  223.         mRecordFragments = new Stack<>();
  224.  
  225.         //Creating new CSV File:
  226.         // Toggle Button
  227.         modeSwitch = (Switch)  findViewById(R.id.model_switch);
  228.  
  229.  
  230.         /////////////////////////////////////////////////////////////////////////////////////////////////
  231.         /////////////////////////////////////////////////////////////////////////////////////////////////
  232.         /////////////////////////////////////////////////////////////////////////////////////////////////
  233.         //timeinfo = (TextView)findViewById(R.id.charger);
  234.  
  235.         timeinfo = (TextView)findViewById(R.id.timeStat);
  236.         hrinfo = (TextView)findViewById(R.id.hrStat);;
  237.         oxinfo = (TextView)findViewById(R.id.oxStat);;
  238.         tenoinfo = (TextView)findViewById(R.id.tempStat);;
  239.         audioInfo = (TextView)findViewById(R.id.audioStat);
  240.         stretchInfo = (TextView)findViewById(R.id.stretchStat);
  241.  
  242.         // Declaring ypr texts
  243.         yawInfo = (TextView)findViewById(R.id.yawStat);
  244.         pitchInfo = (TextView)findViewById(R.id.pitchStat);
  245.         rollInfo = (TextView)findViewById(R.id.rollStat);
  246.         //
  247.  
  248.         text = (TextView)findViewById(R.id.text);
  249.         //message = (EditText)findViewById(R.id.message);       //This is a message sending window
  250.         send = (Button)findViewById(R.id.send);
  251.         scrollView = (ScrollView) findViewById(R.id.scrollView);
  252.  
  253.         text.setMovementMethod(new ScrollingMovementMethod());
  254.         ////////////////////////////////////////////////////////////////////////////////////////////
  255.         send.setEnabled(false);
  256.         ////////////////////////////////////////////////////////////////////////////////////////////
  257.         b = new Bluetooth(this);
  258.         b.enableBluetooth();
  259.  
  260.         b.setCommunicationCallback(this);
  261.  
  262.         int pos = getIntent().getExtras().getInt("pos");
  263.         name = b.getPairedDevices().get(pos).getName();
  264.  
  265.         Display("Connecting...");
  266.         b.connectToDevice(b.getPairedDevices().get(pos));
  267.  
  268.         send.setOnClickListener(new View.OnClickListener() {
  269.             @Override
  270.             public void onClick(View v) {
  271.             b.send("s");
  272.                 /*
  273.             String msg = message.getText().toString();
  274.             message.setText("");
  275.             b.send(msg);
  276.             Display("You: "+msg);
  277.             */
  278.             }
  279.         });
  280.  
  281.         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
  282.         registerReceiver(mReceiver, filter);
  283.         registered=true;
  284.  
  285.         // Working with visualization charts
  286.  
  287.         mChart1 = (LineChart) findViewById(R.id.mChart1);
  288.         mChart1.setDescription("");
  289.         mChart1.setNoDataTextDescription("No data for the moment");
  290.  
  291.         mChart1.setHighlightEnabled(true); ///////////////////////////////////
  292.  
  293.         //enable touch gestures
  294.         mChart1.setTouchEnabled(true);
  295.  
  296.         // enable scaling and dragging
  297.         mChart1.setDragEnabled(true);
  298.         mChart1.setScaleEnabled(true);
  299.         mChart1.setDrawGridBackground(false);
  300.  
  301.         // enable pinch zoom to avoid x and y axis separately
  302.         mChart1.setPinchZoom(true);
  303.  
  304.         // alternative background color
  305.         mChart1.setBackgroundColor(Color.LTGRAY);
  306.  
  307.         // now work on data
  308.         LineData data1 = new LineData();
  309.         data1.setValueTextColor(Color.WHITE);
  310.  
  311.         // add data to line chart
  312.         mChart1.setData(data1);
  313.  
  314.         // get legend object
  315.         Legend l = mChart1.getLegend();
  316.  
  317.         //customize legend
  318.         l.setForm(Legend.LegendForm.LINE);
  319.         l.setTextColor(Color.WHITE);
  320.  
  321.         XAxis x1 = mChart1.getXAxis();
  322.         x1.setTextColor(Color.WHITE);
  323.         x1.setDrawGridLines(false);
  324.         x1.setAvoidFirstLastClipping(true);
  325.  
  326.         YAxis y1 = mChart1.getAxisLeft();
  327.         y1.setTextColor(Color.WHITE);
  328.         y1.setAxisMaxValue(120f);  ///////////////////////////////////
  329. //        y1.setStartAtZero(true);
  330.         y1.setDrawGridLines(true);
  331.  
  332.         YAxis y12 = mChart1.getAxisRight();
  333.         y12.setEnabled(false);
  334.  
  335.  
  336.  
  337.         ////// Toggle Button Switch
  338.         linechartLayout = (RelativeLayout)findViewById(R.id.linechartLayout);
  339.         sensorsGridLayout = (GridLayout)findViewById(R.id.sensorsGridLayout);
  340.  
  341.  
  342.  
  343.         modeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
  344.  
  345.  
  346.  
  347.             @Override
  348.             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  349.                 if (isChecked) {
  350.                     // do something when checked is selected
  351.                     linechartLayout.setVisibility(RelativeLayout.INVISIBLE);
  352.                     sensorsGridLayout.setVisibility(GridLayout.VISIBLE);
  353.                 } else {
  354.                     //do something when unchecked
  355.                     linechartLayout.setVisibility(RelativeLayout.VISIBLE);
  356.                     sensorsGridLayout.setVisibility(GridLayout.INVISIBLE);
  357.                 }
  358.             }
  359.         });
  360.     }
  361.  
  362.     @Override
  363.     protected void onDestroy() {
  364.         super.onDestroy();
  365.         stopRecorder();
  366.         releaseRecorder(true);
  367.         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  368.         if(registered) {
  369.             unregisterReceiver(mReceiver);
  370.             registered=false;
  371.         }
  372.         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  373.         try {
  374.             writer.close();
  375.         } catch (IOException e) {
  376.             e.printStackTrace();
  377.         }
  378.         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  379.     }
  380.  
  381.     @Override
  382.     protected void onResume() {
  383.         super.onResume();
  384.  
  385.         if (doAfterAllPermissionsGranted != null) {
  386.             doAfterAllPermissionsGranted.run();
  387.             doAfterAllPermissionsGranted = null;
  388.         } else {
  389.             String[] neededPermissions = {
  390.                     Manifest.permission.CAMERA,
  391.                     Manifest.permission.RECORD_AUDIO,
  392.                     Manifest.permission.WRITE_EXTERNAL_STORAGE,
  393.             };
  394.             List<String> deniedPermissions = new ArrayList<>();
  395.             for (String permission : neededPermissions) {
  396.                 if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
  397.                     deniedPermissions.add(permission);
  398.                 }
  399.             }
  400.             if (deniedPermissions.isEmpty()) {
  401.                 // All permissions are granted
  402.                 doAfterAllPermissionsGranted();
  403.             } else {
  404.                 String[] array = new String[deniedPermissions.size()];
  405.                 array = deniedPermissions.toArray(array);
  406.                 ActivityCompat.requestPermissions(this, array, REQUEST_PERMISSIONS);
  407.             }
  408.         }
  409.  
  410.  
  411.     }
  412.  
  413.     @Override
  414.     protected void onPause() {
  415.         super.onPause();
  416.         pauseRecording();
  417.         stopRecording();
  418.         stopPreview();
  419.         releaseCamera();
  420.     }
  421.  
  422.     @Override
  423.     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  424.         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  425.         if (requestCode == REQUEST_PERMISSIONS) {
  426.             boolean permissionsAllGranted = true;
  427.             for (int grantResult : grantResults) {
  428.                 if (grantResult != PackageManager.PERMISSION_GRANTED) {
  429.                     permissionsAllGranted = false;
  430.                     break;
  431.                 }
  432.             }
  433.             if (permissionsAllGranted) {
  434.                 doAfterAllPermissionsGranted = new Runnable() {
  435.                     @Override
  436.                     public void run() {
  437.                         doAfterAllPermissionsGranted();
  438.                     }
  439.                 };
  440.             } else {
  441.                 doAfterAllPermissionsGranted = new Runnable() {
  442.                     @Override
  443.                     public void run() {
  444.                         Toast.makeText(FFmpegRecordActivity.this, R.string.permissions_denied_exit, Toast.LENGTH_SHORT).show();
  445.                         finish();
  446.                     }
  447.                 };
  448.             }
  449.         }
  450.     }
  451.  
  452.     @Override
  453.     public void onSurfaceTextureAvailable(final SurfaceTexture surface, int width, int height1) {
  454.         startPreview(surface);
  455.     }
  456.  
  457.     @Override
  458.     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  459.     }
  460.  
  461.     @Override
  462.     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
  463.         return true;
  464.     }
  465.  
  466.     @Override
  467.     public void onSurfaceTextureUpdated(SurfaceTexture surface) {
  468.     }
  469.  
  470.     @Override
  471.     public void onClick(View v) {
  472.         int i = v.getId();
  473.         if (i == R.id.btn_resume_or_pause) {
  474.             if (mRecording) {
  475.                 pauseRecording();
  476.             } else {
  477.                 resumeRecording();
  478.                 ////////////////////////////////////////////////////////////////////////////////////////////////
  479.             }
  480.  
  481.         } else if (i == R.id.btn_done) {
  482.             pauseRecording();
  483.             // check video length
  484.             if (calculateTotalRecordedTime(mRecordFragments) < MIN_VIDEO_LENGTH) {
  485.                 Toast.makeText(this, R.string.video_too_short, Toast.LENGTH_SHORT).show();
  486.                 return;
  487.             }
  488.             new FinishRecordingTask().execute();
  489.  
  490.         } else if (i == R.id.btn_switch_camera) {
  491.             final SurfaceTexture surfaceTexture = mPreview.getSurfaceTexture();
  492.             new ProgressDialogTask<Void, Integer, Void>(R.string.please_wait) {
  493.  
  494.                 @Override
  495.                 protected Void doInBackground(Void... params) {
  496.                     stopRecording();
  497.                     stopPreview();
  498.                     releaseCamera();
  499.  
  500.                     mCameraId = (mCameraId + 1) % 2;
  501.  
  502.                     acquireCamera();
  503.                     startPreview(surfaceTexture);
  504.                     startRecording();
  505.                     return null;
  506.                 }
  507.             }.execute();
  508.  
  509.         } else if (i == R.id.btn_reset) {
  510.             pauseRecording();
  511.             new ProgressDialogTask<Void, Integer, Void>(R.string.please_wait) {
  512.  
  513.                 @Override
  514.                 protected Void doInBackground(Void... params) {
  515.                     stopRecording();
  516.                     stopRecorder();
  517.  
  518.                     startRecorder();
  519.                     startRecording();
  520.                     ////////////////////////////////////////////////////////////////////////////////////////////////
  521.  
  522.                     return null;
  523.                 }
  524.             }.execute();
  525.         }
  526.     }
  527.  
  528.  
  529.     private void doAfterAllPermissionsGranted() {
  530.         acquireCamera();
  531.         SurfaceTexture surfaceTexture = mPreview.getSurfaceTexture();
  532.         if (surfaceTexture != null) {
  533.             // SurfaceTexture already created
  534.             startPreview(surfaceTexture);
  535.         }
  536.         new ProgressDialogTask<Void, Integer, Void>(R.string.initiating) {
  537.  
  538.             @Override
  539.             protected Void doInBackground(Void... params) {
  540.                 if (mFrameRecorder == null) {
  541.                     try {
  542.                         initRecorder();
  543.                     } catch (IOException e) {
  544.                         e.printStackTrace();
  545.                     }
  546.                     startRecorder();
  547.                 }
  548.                 startRecording();
  549.                 return null;
  550.             }
  551.         }.execute();
  552.     }
  553.  
  554.     private void setPreviewSize(int width, int height) {
  555.         if (MiscUtils.isOrientationLandscape(this)) {
  556.             mPreview.setPreviewSize(width, height);
  557.         } else {
  558.             // Swap width and height
  559.             mPreview.setPreviewSize(height, width);
  560.         }
  561.     }
  562.  
  563.     private void startPreview(SurfaceTexture surfaceTexture) {
  564.         if (mCamera == null) {
  565.             return;
  566.         }
  567.  
  568.         Camera.Parameters parameters = mCamera.getParameters();
  569.         List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
  570.         Camera.Size previewSize = CameraHelper.getOptimalSize(previewSizes,
  571.                 PREFERRED_PREVIEW_WIDTH, PREFERRED_PREVIEW_HEIGHT);
  572.         // if changed, reassign values and request layout
  573.         if (mPreviewWidth != previewSize.width || mPreviewHeight != previewSize.height) {
  574.             mPreviewWidth = previewSize.width;
  575.             mPreviewHeight = previewSize.height;
  576.             setPreviewSize(mPreviewWidth, mPreviewHeight);
  577.             mPreview.requestLayout();
  578.         }
  579.         parameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
  580. //        parameters.setPreviewFormat(ImageFormat.NV21);
  581.         mCamera.setParameters(parameters);
  582.  
  583.         mCamera.setDisplayOrientation(CameraHelper.getCameraDisplayOrientation(
  584.                 this, mCameraId));
  585.  
  586.         // YCbCr_420_SP (NV21) format
  587.         byte[] bufferByte = new byte[mPreviewWidth * mPreviewHeight * 3 / 2];
  588.         mCamera.addCallbackBuffer(bufferByte);
  589.         mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
  590.  
  591.             private long lastPreviewFrameTime;
  592.  
  593.             @Override
  594.             public void onPreviewFrame(byte[] data, Camera camera) {
  595.                 long thisPreviewFrameTime = System.currentTimeMillis();
  596.                 if (lastPreviewFrameTime > 0) {
  597.                     Log.d(LOG_TAG, "Preview frame interval: " + (thisPreviewFrameTime - lastPreviewFrameTime) + "ms");
  598.                 }
  599.                 lastPreviewFrameTime = thisPreviewFrameTime;
  600.  
  601.                 // get video data
  602.                 if (mRecording) {
  603.                     if (mAudioRecordThread == null || !mAudioRecordThread.isRunning()) {
  604.                         // wait for AudioRecord to init and start
  605.                         mRecordFragments.peek().setStartTimestamp(System.currentTimeMillis());
  606.                     } else {
  607.                         // pop the current record fragment when calculate total recorded time
  608.                         RecordFragment curFragment = mRecordFragments.pop();
  609.                         long recordedTime = calculateTotalRecordedTime(mRecordFragments);
  610.                         // push it back after calculation
  611.                         mRecordFragments.push(curFragment);
  612.                         long curRecordedTime = System.currentTimeMillis()
  613.                                 - curFragment.getStartTimestamp() + recordedTime;
  614.                         // check if exceeds time limit
  615.                         if (curRecordedTime > MAX_VIDEO_LENGTH) {
  616.                             pauseRecording();
  617.                             new FinishRecordingTask().execute();
  618.                             return;
  619.                         }
  620.  
  621.                         long timestamp = 1000 * curRecordedTime;
  622.                         Frame frame;
  623.                         FrameToRecord frameToRecord = mRecycledFrameQueue.poll();
  624.                         if (frameToRecord != null) {
  625.                             frame = frameToRecord.getFrame();
  626.                             frameToRecord.setTimestamp(timestamp);
  627.                         } else {
  628.                             frame = new Frame(mPreviewWidth, mPreviewHeight, frameDepth, frameChannels);
  629.                             frameToRecord = new FrameToRecord(timestamp, frame);
  630.                         }
  631.                         ((ByteBuffer) frame.image[0].position(0)).put(data);
  632.  
  633.                         if (mFrameToRecordQueue.offer(frameToRecord)) {
  634.                             mFrameToRecordCount++;
  635.                         }
  636.                     }
  637.                 }
  638.                 mCamera.addCallbackBuffer(data);
  639.             }
  640.         });
  641.  
  642.         try {
  643.             mCamera.setPreviewTexture(surfaceTexture);
  644.         } catch (IOException ioe) {
  645.             ioe.printStackTrace();
  646.         }
  647.         mCamera.startPreview();
  648.     }
  649.  
  650.     private void stopPreview() {
  651.         if (mCamera != null) {
  652.             mCamera.stopPreview();
  653.             mCamera.setPreviewCallbackWithBuffer(null);
  654.         }
  655.     }
  656.  
  657.     private void acquireCamera() {
  658.         try {
  659.             mCamera = Camera.open(mCameraId);
  660.         } catch (Exception e) {
  661.             e.printStackTrace();
  662.         }
  663.     }
  664.  
  665.     private void releaseCamera() {
  666.         if (mCamera != null) {
  667.             mCamera.release();        // release the camera for other applications
  668.             mCamera = null;
  669.         }
  670.     }
  671.  
  672.     private void initRecorder() throws IOException {
  673.         Log.i(LOG_TAG, "init mFrameRecorder");
  674.  
  675.         String recordedTime = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
  676.         mVideo = CameraHelper.getOutputMediaFile(recordedTime, CameraHelper.MEDIA_TYPE_VIDEO);
  677.         mText = CameraHelper.getOutputMediaFile(recordedTime, CameraHelper.MEDIA_TYPE_TEXT);
  678.         ////////////////////////////////////////////////////////////////////////////////////////////////
  679.  
  680.  
  681.        try {
  682.             writer = new FileWriter(mText);
  683.             /*
  684.             writer.append("ID");
  685.             writer.append(",");
  686.             writer.append("Time");
  687.             writer.append(",");
  688.             writer.append("HR");
  689.             writer.append(",");
  690.             writer.append("Ox Rate");
  691.             writer.append(",");
  692.             writer.append("Temp");
  693.             writer.append("\n");
  694.             writer.flush();
  695.             */
  696.             sensorHeaderCheck = true;
  697.         } catch (IOException e) {
  698.             e.printStackTrace();
  699.         }
  700.  
  701.         Log.i(LOG_TAG, "Output Video: " + mVideo);
  702.         Log.i(LOG_TAG, "Output Text: " + mText);
  703.  
  704.         mFrameRecorder = new FFmpegFrameRecorder(mVideo, videoWidth, videoHeight, 1);
  705.         mFrameRecorder.setFormat("mp4");
  706.         mFrameRecorder.setSampleRate(sampleAudioRateInHz);
  707.         mFrameRecorder.setFrameRate(frameRate);
  708.         // Use H264
  709.         mFrameRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
  710.  
  711.         // See: https://trac.ffmpeg.org/wiki/Encode/H.264#crf
  712.         /*
  713.          * The range of the quantizer scale is 0-51: where 0 is lossless, 23 is default, and 51 is worst possible. A lower value is a higher quality and a subjectively sane range is 18-28. Consider 18 to be visually lossless or nearly so: it should look the same or nearly the same as the input but it isn't technically lossless.
  714.          * The range is exponential, so increasing the CRF value +6 is roughly half the bitrate while -6 is roughly twice the bitrate. General usage is to choose the highest CRF value that still provides an acceptable quality. If the output looks good, then try a higher value and if it looks bad then choose a lower value.
  715.          */
  716.         mFrameRecorder.setVideoOption("crf", "28");
  717.         mFrameRecorder.setVideoOption("preset", "superfast");
  718.         mFrameRecorder.setVideoOption("tune", "zerolatency");
  719.  
  720.         Log.i(LOG_TAG, "mFrameRecorder initialize success");
  721.     }
  722.  
  723.     private void releaseRecorder(boolean deleteFile) {
  724.         if (mFrameRecorder != null) {
  725.             try {
  726.                 mFrameRecorder.release();
  727.             } catch (FFmpegFrameRecorder.Exception e) {
  728.                 e.printStackTrace();
  729.             }
  730.             mFrameRecorder = null;
  731.  
  732.             if (deleteFile) {
  733.                 mVideo.delete();
  734.                 mText.delete();
  735.             }
  736.         }
  737.     }
  738.  
  739.     private void startRecorder() {
  740.         try {
  741.             mFrameRecorder.start();
  742.         } catch (FFmpegFrameRecorder.Exception e) {
  743.             e.printStackTrace();
  744.         }
  745.     }
  746.  
  747.     private void stopRecorder() {
  748.         if (mFrameRecorder != null) {
  749.             try {
  750.                 mFrameRecorder.stop();
  751.             } catch (FFmpegFrameRecorder.Exception e) {
  752.                 e.printStackTrace();
  753.             }
  754.         }
  755.  
  756.         mRecordFragments.clear();
  757.  
  758.         runOnUiThread(new Runnable() {
  759.             @Override
  760.             public void run() {
  761.                 mBtnReset.setVisibility(View.INVISIBLE);
  762.             }
  763.         });
  764.     }
  765.  
  766.     private void startRecording() {
  767.         mAudioRecordThread = new AudioRecordThread();
  768.         mAudioRecordThread.start();
  769.         mVideoRecordThread = new VideoRecordThread();
  770.         mVideoRecordThread.start();
  771.         /////////////////////////////////////////////////////////////////////////////////////////
  772.         //resumeBtnPressed = true;
  773.     }
  774.  
  775.     private void stopRecording() {
  776.         if (mAudioRecordThread != null) {
  777.             if (mAudioRecordThread.isRunning()) {
  778.                 mAudioRecordThread.stopRunning();
  779.             }
  780.         }
  781.  
  782.         if (mVideoRecordThread != null) {
  783.             if (mVideoRecordThread.isRunning()) {
  784.                 mVideoRecordThread.stopRunning();
  785.             }
  786.         }
  787.  
  788.         try {
  789.             if (mAudioRecordThread != null) {
  790.                 mAudioRecordThread.join();
  791.             }
  792.             if (mVideoRecordThread != null) {
  793.                 mVideoRecordThread.join();
  794.             }
  795.         } catch (InterruptedException e) {
  796.             e.printStackTrace();
  797.         }
  798.         mAudioRecordThread = null;
  799.         mVideoRecordThread = null;
  800.  
  801.  
  802.         mFrameToRecordQueue.clear();
  803.         mRecycledFrameQueue.clear();
  804.  
  805.  
  806.         resumeBtnPressed = false;
  807.     }
  808.  
  809.     private void resumeRecording() {
  810.         if (!mRecording) {
  811.             RecordFragment recordFragment = new RecordFragment();
  812.             recordFragment.setStartTimestamp(System.currentTimeMillis());
  813.             mRecordFragments.push(recordFragment);
  814.             runOnUiThread(new Runnable() {
  815.                 @Override
  816.                 public void run() {
  817.                     mBtnReset.setVisibility(View.VISIBLE);
  818.                     mBtnSwitchCamera.setVisibility(View.INVISIBLE);
  819.                     mBtnResumeOrPause.setText(R.string.pause);
  820.                 }
  821.             });
  822.             mRecording = true;
  823.             /////////////////////////////////////////////////////////////////////////////////////////
  824.             resumeBtnPressed = true;
  825.         }
  826.     }
  827.  
  828.     private void pauseRecording() {
  829.         if (mRecording) {
  830.             mRecordFragments.peek().setEndTimestamp(System.currentTimeMillis());
  831.             runOnUiThread(new Runnable() {
  832.                 @Override
  833.                 public void run() {
  834.                     mBtnSwitchCamera.setVisibility(View.VISIBLE);
  835.                     mBtnResumeOrPause.setText(R.string.resume);
  836.                 }
  837.             });
  838.             mRecording = false;
  839.             /////////////////////////////////////////////////////////////////////////////////////////
  840.             resumeBtnPressed = false;
  841.         }
  842.     }
  843.  
  844.     private long calculateTotalRecordedTime(Stack<RecordFragment> recordFragments) {
  845.         long recordedTime = 0;
  846.         for (RecordFragment recordFragment : recordFragments) {
  847.             recordedTime += recordFragment.getDuration();
  848.         }
  849.         return recordedTime;
  850.     }
  851.  
  852.     class RunningThread extends Thread {
  853.         boolean isRunning;
  854.  
  855.         public boolean isRunning() {
  856.             return isRunning;
  857.         }
  858.  
  859.         public void stopRunning() {
  860.             this.isRunning = false;
  861.         }
  862.     }
  863.  
  864.     class AudioRecordThread extends RunningThread {
  865.         private AudioRecord mAudioRecord;
  866.         private ShortBuffer audioData;
  867.  
  868.         public AudioRecordThread() {
  869.             int bufferSize = AudioRecord.getMinBufferSize(sampleAudioRateInHz,
  870.                     AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
  871.             mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleAudioRateInHz,
  872.                     AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
  873.  
  874.             audioData = ShortBuffer.allocate(bufferSize);
  875.         }
  876.  
  877.         @Override
  878.         public void run() {
  879.             android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
  880.  
  881.             Log.d(LOG_TAG, "mAudioRecord startRecording");
  882.             mAudioRecord.startRecording();
  883.  
  884.             isRunning = true;
  885.             /* ffmpeg_audio encoding loop */
  886.             while (isRunning) {
  887.                 if (mRecording && mFrameRecorder != null) {
  888.                     int bufferReadResult = mAudioRecord.read(audioData.array(), 0, audioData.capacity());
  889.                     audioData.limit(bufferReadResult);
  890.                     if (bufferReadResult > 0) {
  891.                         Log.v(LOG_TAG, "bufferReadResult: " + bufferReadResult);
  892.                         try {
  893.                             mFrameRecorder.recordSamples(audioData);
  894.                         } catch (FFmpegFrameRecorder.Exception e) {
  895.                             Log.v(LOG_TAG, e.getMessage());
  896.                             e.printStackTrace();
  897.                         }
  898.                     }
  899.                 }
  900.             }
  901.             Log.d(LOG_TAG, "mAudioRecord stopRecording");
  902.             mAudioRecord.stop();
  903.             mAudioRecord.release();
  904.             mAudioRecord = null;
  905.             Log.d(LOG_TAG, "mAudioRecord released");
  906.         }
  907.     }
  908.  
  909.     class VideoRecordThread extends RunningThread {
  910.         @Override
  911.         public void run() {
  912.             int previewWidth = mPreviewWidth;
  913.             int previewHeight = mPreviewHeight;
  914.  
  915.             List<String> filters = new ArrayList<>();
  916.             // Transpose
  917.             String transpose = null;
  918.             String hflip = null;
  919.             String vflip = null;
  920.             String crop = null;
  921.             String scale = null;
  922.             int cropWidth;
  923.             int cropHeight;
  924.             Camera.CameraInfo info = new Camera.CameraInfo();
  925.             Camera.getCameraInfo(mCameraId, info);
  926.             int rotation = getWindowManager().getDefaultDisplay().getRotation();
  927.             switch (rotation) {
  928.                 case Surface.ROTATION_0:
  929.                     switch (info.orientation) {
  930.                         case 270:
  931.                             if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
  932.                                 transpose = "transpose=clock_flip"; // Same as preview display
  933.                             } else {
  934.                                 transpose = "transpose=cclock"; // Mirrored horizontally as preview display
  935.                             }
  936.                             break;
  937.                         case 90:
  938.                             if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
  939.                                 transpose = "transpose=cclock_flip"; // Same as preview display
  940.                             } else {
  941.                                 transpose = "transpose=clock"; // Mirrored horizontally as preview display
  942.                             }
  943.                             break;
  944.                     }
  945.                     cropWidth = previewHeight;
  946.                     cropHeight = cropWidth * videoHeight / videoWidth;
  947.                     crop = String.format("crop=%d:%d:%d:%d",
  948.                             cropWidth, cropHeight,
  949.                             (previewHeight - cropWidth) / 2, (previewWidth - cropHeight) / 2);
  950.                     // swap width and height
  951.                     scale = String.format("scale=%d:%d", videoHeight, videoWidth);
  952.                     break;
  953.                 case Surface.ROTATION_90:
  954.                 case Surface.ROTATION_270:
  955.                     switch (rotation) {
  956.                         case Surface.ROTATION_90:
  957.                             // landscape-left
  958.                             switch (info.orientation) {
  959.                                 case 270:
  960.                                     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
  961.                                         hflip = "hflip";
  962.                                     }
  963.                                     break;
  964.                             }
  965.                             break;
  966.                         case Surface.ROTATION_270:
  967.                             // landscape-right
  968.                             switch (info.orientation) {
  969.                                 case 90:
  970.                                     if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
  971.                                         hflip = "hflip";
  972.                                         vflip = "vflip";
  973.                                     }
  974.                                     break;
  975.                                 case 270:
  976.                                     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
  977.                                         vflip = "vflip";
  978.                                     }
  979.                                     break;
  980.                             }
  981.                             break;
  982.                     }
  983.                     cropHeight = previewHeight;
  984.                     cropWidth = cropHeight * videoWidth / videoHeight;
  985.                     crop = String.format("crop=%d:%d:%d:%d",
  986.                             cropWidth, cropHeight,
  987.                             (previewWidth - cropWidth) / 2, (previewHeight - cropHeight) / 2);
  988.                     scale = String.format("scale=%d:%d", videoWidth, videoHeight);
  989.                     break;
  990.                 case Surface.ROTATION_180:
  991.                     break;
  992.             }
  993.             // transpose
  994.             if (transpose != null) {
  995.                 filters.add(transpose);
  996.             }
  997.             // horizontal flip
  998.             if (hflip != null) {
  999.                 filters.add(hflip);
  1000.             }
  1001.             // vertical flip
  1002.             if (vflip != null) {
  1003.                 filters.add(vflip);
  1004.             }
  1005.             // crop
  1006.             if (crop != null) {
  1007.                 filters.add(crop);
  1008.             }
  1009.             // scale (to designated size)
  1010.             if (scale != null) {
  1011.                 filters.add(scale);
  1012.             }
  1013.  
  1014.             FFmpegFrameFilter frameFilter = new FFmpegFrameFilter(TextUtils.join(",", filters),
  1015.                     previewWidth, previewHeight);
  1016.             frameFilter.setPixelFormat(avutil.AV_PIX_FMT_NV21);
  1017.             frameFilter.setFrameRate(frameRate);
  1018.             try {
  1019.                 frameFilter.start();
  1020.             } catch (FrameFilter.Exception e) {
  1021.                 e.printStackTrace();
  1022.             }
  1023.  
  1024.             isRunning = true;
  1025.             FrameToRecord recordedFrame;
  1026.  
  1027.             while (isRunning || !mFrameToRecordQueue.isEmpty()) {
  1028.                 try {
  1029.                     recordedFrame = mFrameToRecordQueue.take();
  1030.                 } catch (InterruptedException ie) {
  1031.                     ie.printStackTrace();
  1032.                     try {
  1033.                         frameFilter.stop();
  1034.                     } catch (FrameFilter.Exception e) {
  1035.                         e.printStackTrace();
  1036.                     }
  1037.                     break;
  1038.                 }
  1039.  
  1040.                 if (mFrameRecorder != null) {
  1041.                     long timestamp = recordedFrame.getTimestamp();
  1042.                     if (timestamp > mFrameRecorder.getTimestamp()) {
  1043.                         mFrameRecorder.setTimestamp(timestamp);
  1044.                     }
  1045.                     long startTime = System.currentTimeMillis();
  1046. //                    Frame filteredFrame = recordedFrame.getFrame();
  1047.                     Frame filteredFrame = null;
  1048.                     try {
  1049.                         frameFilter.push(recordedFrame.getFrame());
  1050.                         filteredFrame = frameFilter.pull();
  1051.                     } catch (FrameFilter.Exception e) {
  1052.                         e.printStackTrace();
  1053.                     }
  1054.                     try {
  1055.                         mFrameRecorder.record(filteredFrame);
  1056.                     } catch (FFmpegFrameRecorder.Exception e) {
  1057.                         e.printStackTrace();
  1058.                     }
  1059.                     long endTime = System.currentTimeMillis();
  1060.                     long processTime = endTime - startTime;
  1061.                     mTotalProcessFrameTime += processTime;
  1062.                     Log.d(LOG_TAG, "This frame process time: " + processTime + "ms");
  1063.                     long totalAvg = mTotalProcessFrameTime / ++mFrameRecordedCount;
  1064.                     Log.d(LOG_TAG, "Avg frame process time: " + totalAvg + "ms");
  1065.                 }
  1066.                 Log.d(LOG_TAG, mFrameRecordedCount + " / " + mFrameToRecordCount);
  1067.                 mRecycledFrameQueue.offer(recordedFrame);
  1068.             }
  1069.         }
  1070.  
  1071.         public void stopRunning() {
  1072.             super.stopRunning();
  1073.             if (getState() == WAITING) {
  1074.                 interrupt();
  1075.             }
  1076.         }
  1077.     }
  1078.  
  1079.     abstract class ProgressDialogTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
  1080.  
  1081.         private int promptRes;
  1082.         private ProgressDialog mProgressDialog;
  1083.  
  1084.         public ProgressDialogTask(int promptRes) {
  1085.             this.promptRes = promptRes;
  1086.         }
  1087.  
  1088.         @Override
  1089.         protected void onPreExecute() {
  1090.             super.onPreExecute();
  1091.             mProgressDialog = ProgressDialog.show(FFmpegRecordActivity.this,
  1092.                     null, getString(promptRes), true);
  1093.         }
  1094.  
  1095.         @Override
  1096.         protected void onProgressUpdate(Progress... values) {
  1097.             super.onProgressUpdate(values);
  1098. //            mProgressDialog.setProgress(values[0]);
  1099.         }
  1100.  
  1101.         @Override
  1102.         protected void onPostExecute(Result result) {
  1103.             super.onPostExecute(result);
  1104.             mProgressDialog.dismiss();
  1105.         }
  1106.     }
  1107.  
  1108.     class FinishRecordingTask extends ProgressDialogTask<Void, Integer, Void> {
  1109.  
  1110.         public FinishRecordingTask() {
  1111.             super(R.string.processing);
  1112.         }
  1113.  
  1114.         @Override
  1115.         protected Void doInBackground(Void... params) {
  1116.             stopRecording();
  1117.             stopRecorder();
  1118.             releaseRecorder(false);
  1119.             return null;
  1120.         }
  1121.  
  1122.         // Declaring values for statistics calculation
  1123. //        private float hrAvg;
  1124. //        private float oxAvg;
  1125. //        private float tempAvg;
  1126. //        private float audioAvg;
  1127. //        private float stretchAvg;
  1128. //        private float yawAvg;
  1129. //        private float pitchAvg;
  1130. //        private float rollAvg;
  1131.  
  1132.  
  1133. //        hrTtl = hrTtl + hr_only_float;
  1134. //        oxTtl = oxTtl + ox_only_float;
  1135. //        tempTtl = tempTtl + temp_only_float;
  1136. //        audioTtl = audioTtl + audio_only_float;
  1137. //        stretchTtl = stretchTtl + stretch_only_float;
  1138. //        yawTtl = yawTtl + yaw_only_float;
  1139. //        pitchTtl = pitchTtl + pitch_only_float;
  1140. //        rollTtl = rollTtl + roll_only_float;
  1141.  
  1142.  
  1143.  
  1144. //        hrAvg =
  1145. //        oxAvg
  1146. //        tempAvg
  1147.  
  1148.  
  1149.  
  1150.  
  1151.         @Override
  1152.         protected void onPostExecute(Void aVoid) {
  1153.             super.onPostExecute(aVoid);
  1154.             ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1155.  
  1156.             Intent intent = new Intent(FFmpegRecordActivity.this, PlaybackActivity.class);
  1157.             intent.putExtra(PlaybackActivity.INTENT_NAME_VIDEO_PATH, mVideo.getPath());
  1158.             //intent.putExtra(PlaybackActivity.INTENT_NAME_TEXT_PATH, mText.getPath());
  1159.             intent.putExtra(PlaybackActivity.INTENT_NAME_TEXT_PATH, mText.getPath());
  1160.             startActivity(intent);
  1161.  
  1162.         }
  1163.     }
  1164.  
  1165.  
  1166.     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1167.     @Override
  1168.     public boolean onCreateOptionsMenu(Menu menu) {
  1169.         MenuInflater inflater = getMenuInflater();
  1170.         inflater.inflate(R.menu.menu_main, menu);
  1171.         return true;
  1172.     }
  1173.  
  1174.     @Override
  1175.     public boolean onOptionsItemSelected(MenuItem item) {
  1176.         // Handle item selection
  1177.         switch (item.getItemId()) {
  1178.             case R.id.close:
  1179.                 b.removeCommunicationCallback();
  1180.                 b.disconnect();
  1181.                 Intent intent = new Intent(this, Select.class);
  1182.                 startActivity(intent);
  1183.                 finish();
  1184.                 return true;
  1185.  
  1186.             case R.id.rate:
  1187.                 Uri uri = Uri.parse("market://details?id=" + this.getPackageName());
  1188.                 Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
  1189.                 goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
  1190.                 try {
  1191.                     startActivity(goToMarket);
  1192.                 } catch (ActivityNotFoundException e) {
  1193.                     startActivity(new Intent(Intent.ACTION_VIEW,
  1194.                             Uri.parse("http://play.google.com/store/apps/details?id=" + this.getPackageName())));
  1195.                 }
  1196.                 return true;
  1197.             default:
  1198.                 return super.onOptionsItemSelected(item);
  1199.         }
  1200.     }
  1201.  
  1202.     public void Display(final String s){
  1203.         this.runOnUiThread(new Runnable() {
  1204.             @Override
  1205.             public void run() {
  1206.                 text.append(s + "\n");
  1207.                 scrollView.fullScroll(View.FOCUS_DOWN);
  1208.             }
  1209.         });
  1210.     }
  1211.     ////////////////////////////////////////////////////////////////////////////////////////////////
  1212.  
  1213.     @Override
  1214.     public void onConnect(BluetoothDevice device) {
  1215.         Display("Connected to "+device.getName()+" - "+device.getAddress());
  1216.         this.runOnUiThread(new Runnable() {
  1217.             @Override
  1218.             public void run() {
  1219.                 ////////////////////////////////////////////////////////////////////////////////////////////////
  1220.                 send.setEnabled(true);
  1221.                 ////////////////////////////////////////////////////////////////////////////////////////////////
  1222.             }
  1223.         });
  1224.     }
  1225.  
  1226.     ////////////////////////////////////////////////////////////////////////////////////////////////
  1227.     @Override
  1228.     public void onDisconnect(BluetoothDevice device, String message) {
  1229.         Display("Disconnected!");
  1230.         Display("Connecting again...");
  1231.         b.connectToDevice(device);
  1232.     }
  1233.  
  1234.     //File root = new File(DIRECTORY_PATH);
  1235.     //File gpxfile = new File(root, "samples.txt");
  1236.  
  1237.     @RequiresApi(api = Build.VERSION_CODES.O)
  1238.     @Override
  1239.     public void onMessage(String message) {
  1240.  
  1241.         //FileOutputStream outputStream;
  1242.          /*else {
  1243.             try {
  1244.                 mText = CameraHelper.getOutputMediaFile(recordedTime, CameraHelper.MEDIA_TYPE_TEXT);
  1245.                 FileWriter writer = new FileWriter(mText);
  1246.                 writer.append("First string is here to be written.");
  1247.                 writer.flush();
  1248.                 writer.close();
  1249.             } catch (IOException e) {
  1250.                 e.printStackTrace();
  1251.             }
  1252.         }*/
  1253.         ///////////////////////////////////////////////////////////////////////////////////////
  1254. /*        if (sensorValueIndex == 0) {
  1255.             sensorHeaderCheck = true;
  1256.             try {
  1257.                 /////////////////////////////////////////////////////
  1258.                 //writer.append(message);
  1259.                 /////////////////////////////////////////////////////
  1260.                 writer.append("ID");
  1261.                 writer.append(",");
  1262.                 writer.append("Time");
  1263.                 writer.append(",");
  1264.                 writer.append("HR");
  1265.                 writer.append(",");
  1266.                 writer.append("Ox Rate");
  1267.                 writer.append(",");
  1268.                 writer.append("Temp");
  1269.                 writer.append("\n");
  1270.                 writer.flush();
  1271.                 //writer.close();
  1272.             } catch (IOException e) {
  1273.                 e.printStackTrace();
  1274.             }
  1275.         }*/
  1276.         ///////////////////////////////////////////////////////////////////////////////////////
  1277.  
  1278.         //if (resumeBtnPressed == true) {
  1279.             ///////////////////////////////////////////////////////////////////////////////////////
  1280.             int first = message.indexOf("/");
  1281.             int second = message.indexOf("/",first+1);
  1282.             int third = message.indexOf("/",second+1);
  1283.             int fourth = message.indexOf("/",third+1);
  1284.             int fivth = message.indexOf("/",fourth+1);
  1285.             int sixth = message.indexOf("/",fivth+1);
  1286.             int seventh = message.indexOf("/",sixth+1);
  1287.             int eighth = message.indexOf("/",seventh+1);
  1288.             int ninth = message.indexOf("/",eighth+1);
  1289.             int tenth = message.indexOf("/",ninth+1);
  1290.             int eleventh = message.indexOf("/",tenth+1);
  1291.             int twelfth = message.indexOf("/",eleventh+1);
  1292.             int thirteenth = message.indexOf("/",twelfth+1);
  1293.             int fourteenth = message.indexOf("/",thirteenth+1);
  1294.             int fifteenth = message.indexOf("/",fourteenth+1);
  1295.             int sixteenth = message.indexOf("/",fifteenth+1);
  1296.             int seventeenth = message.indexOf("/",sixteenth+1);
  1297.  
  1298.             String index_header = "Order";
  1299.             String time_header = "Time";
  1300.             String hr_header = "HR";
  1301.             String ox_header = "Ox";
  1302.             String temp_header = "Temp";
  1303.             String stretch_header = "Stretch";
  1304.             String audio_header = "Audio";
  1305.             String yaw_header = "Yaw";
  1306.             String pitch_header = "Pitch";
  1307.             String roll_jeader = "Roll";
  1308.  
  1309.             final String index_only = String.valueOf(sensorValueIndex);
  1310.             final String time_only = message.substring(first+1,second);
  1311.             final String hr_only = message.substring(third+1,fourth);
  1312.             final String ox_only = message.substring(fivth+1,sixth);
  1313.             final String temp_only = message.substring(seventh+1,eighth);
  1314.             final String yaw_only = message.substring(ninth+1,tenth);
  1315.             final String pitch_only = message.substring(eleventh+1,twelfth);
  1316.             final String roll_only = message.substring(thirteenth+1,fourteenth);
  1317.             final String audio_only = message.substring(fifteenth+1,sixteenth);
  1318.             final String stretch_only = message.substring(seventeenth+1,message.length()-1);
  1319.  
  1320.             final float hr_only_float  = Float.parseFloat(hr_only);
  1321.             float ox_only_float  = Float.parseFloat(ox_only);
  1322.             float temp_only_float  = Float.parseFloat(temp_only);
  1323.             float yaw_only_float  = Float.parseFloat(yaw_only);
  1324.             float pitch_only_float  = Float.parseFloat(pitch_only);
  1325.             float roll_only_float  = Float.parseFloat(roll_only);
  1326.             float audio_only_float = Float.parseFloat(audio_only);
  1327.             float stretch_only_float = Float.parseFloat(stretch_only);
  1328.  
  1329.             hrTtl = hrTtl + hr_only_float;
  1330.             oxTtl = oxTtl + ox_only_float;
  1331.             tempTtl = tempTtl + temp_only_float;
  1332.             audioTtl = audioTtl + audio_only_float;
  1333.             stretchTtl = stretchTtl + stretch_only_float;
  1334.             yawTtl = yawTtl + yaw_only_float;
  1335.             pitchTtl = pitchTtl + pitch_only_float;
  1336.             rollTtl = rollTtl + roll_only_float;
  1337.  
  1338.             sensValCount = sensValCount + 1;
  1339.  
  1340.             runOnUiThread(new Runnable() {
  1341.                 @Override
  1342.                 public void run() {
  1343.                     timeinfo.setText(time_only);
  1344.                     hrinfo.setText(hr_only);
  1345.                     oxinfo.setText(ox_only);
  1346.                     tenoinfo.setText(temp_only);
  1347.                     // Later added
  1348.                     yawInfo.setText(yaw_only);
  1349.                     pitchInfo.setText(pitch_only);
  1350.                     rollInfo.setText(roll_only);
  1351.                     audioInfo.setText(audio_only);
  1352.                     stretchInfo.setText(stretch_only);
  1353. //stuff that updates ui
  1354. ////
  1355.                 }
  1356.             });
  1357.  
  1358.         new Thread(new Runnable() {
  1359.             @Override
  1360.             public void run() {
  1361.                 // add 100 entries
  1362.                 for (int i = 0; i < 200; i++) {
  1363.                     runOnUiThread(new Runnable() {
  1364.                         @Override
  1365.                         public void run() {
  1366.  
  1367.  
  1368.                             LineData data = mChart1.getData();
  1369.                             //--//
  1370.                             if (data != null) {
  1371.                                 LineDataSet set = (LineDataSet) data.getDataSetByIndex(0);
  1372.  
  1373.                                 if (set == null) {
  1374.                                     set = createSet();
  1375.                                     data.addDataSet(set);
  1376.                                 }
  1377.  
  1378.                                 // add a new random value
  1379.                                 data.addXValue("");
  1380.                                 data.addEntry(new Entry(hr_only_float, set.getEntryCount()),0);
  1381.  
  1382.                                 //enable chart data has changed
  1383.                                 mChart1.notifyDataSetChanged();
  1384.  
  1385.                                 // limit number of visible entries
  1386.                                 //mChart.setVisibleXRange(5,7);
  1387.                                 mChart1.setVisibleXRange(6);
  1388.  
  1389.                                 // scroll to the last entry
  1390.                                 //mChart.moveViewToX(data.getEntryCount() - 7);
  1391.  
  1392.                                 mChart1.moveViewToX(data.getXValCount() - 7);
  1393.                             }
  1394.                             //--/
  1395.  
  1396.                         }
  1397.                     });
  1398.  
  1399.                     // pause between adds
  1400.                     try {
  1401.                         Thread.sleep(600);
  1402.                     } catch (InterruptedException e) {
  1403.                         // manage errors
  1404.                         //e.printStackTrace();
  1405.                     }
  1406.                 }
  1407.             }
  1408.         }).start();
  1409.  
  1410.             Display(name+": "+message);
  1411.  
  1412.             //File file = new File("foo.csv");
  1413.  
  1414.             /*
  1415.             CsvWriter csvWriter = new CsvWriter();
  1416.             //if (mText.exists()) {
  1417.             //////////////////////////////////////////////////////////////////////////////////////////
  1418.             //try (CsvAppender csvAppender = csvWriter.append(mText, StandardCharsets.UTF_8)) {
  1419.             try (CsvAppender csvAppender = csvWriter.append(file, StandardCharsets.UTF_8)) {
  1420.                 csvAppender.appendLine("header1", "header2");
  1421.                 // 1st line in one operation
  1422.                 csvAppender.appendLine("value1", "value2");
  1423.                 csvAppender.endLine();
  1424.             } catch (IOException e) {
  1425.                 e.printStackTrace();
  1426.             }
  1427.             */
  1428.             if (sensorValueIndex == 0) {
  1429.                 try {
  1430.                     /////////////////////////////////////////////////////
  1431.                     //writer.append(message);
  1432.                     /////////////////////////////////////////////////////
  1433.                     writer.append(index_header);
  1434.                     writer.append(",");
  1435.                     writer.append(time_header);
  1436.                     writer.append(",");
  1437.                     writer.append(hr_header);
  1438.                     writer.append(",");
  1439.                     writer.append(ox_header);
  1440.                     writer.append(",");
  1441.                     writer.append(temp_header);
  1442.                     writer.append(",");
  1443.                     writer.append(stretch_header);
  1444.                     writer.append(",");
  1445.                     writer.append(audio_header);
  1446.                     writer.append(",");
  1447.                     writer.append(yaw_header);
  1448.                     writer.append(",");
  1449.                     writer.append(pitch_header);
  1450.                     writer.append(",");
  1451.                     writer.append(roll_jeader);
  1452.                     writer.append("\n");
  1453.                     writer.flush();
  1454.                     sensorValueIndex = sensorValueIndex + 1;
  1455.                     //writer.close();
  1456.                 } catch (IOException e) {
  1457.                     e.printStackTrace();
  1458.                 }
  1459.             } else {
  1460.                 try {
  1461.  
  1462.                     /////////////////////////////////////////////////////
  1463.                     //writer.append(message);
  1464.                     /////////////////////////////////////////////////////
  1465.                     writer.append(index_only);
  1466.                     writer.append(",");
  1467.                     writer.append(time_only);
  1468.                     writer.append(",");
  1469.                     writer.append(hr_only);
  1470.                     writer.append(",");
  1471.                     writer.append(ox_only);
  1472.                     writer.append(",");
  1473.                     writer.append(temp_only);
  1474.                     writer.append(",");
  1475.                     writer.append(stretch_only);
  1476.                     writer.append(",");
  1477.                     writer.append(audio_only);
  1478.                     writer.append(",");
  1479.                     writer.append(yaw_only);
  1480.                     writer.append(",");
  1481.                     writer.append(pitch_only);
  1482.                     writer.append(",");
  1483.                     writer.append(roll_only);
  1484.                     writer.append("\n");
  1485.                     writer.flush();
  1486.                     sensorValueIndex = sensorValueIndex + 1;
  1487.                     //writer.close();
  1488.                 } catch (IOException e) {
  1489.                     e.printStackTrace();
  1490.                 }
  1491.             }
  1492.  
  1493.  
  1494.  
  1495.             //if (sensorHeaderCheck == true) {
  1496.  
  1497.             //}
  1498.  
  1499.             //////////////////////////////////////////////////////////////////////////////////////////
  1500.             //}
  1501. /*            try {
  1502.                 outputStream = openFileOutput("logslogslogs", Context.MODE_PRIVATE);
  1503.                 outputStream.write(message.getBytes());
  1504.                 outputStream.close();
  1505.                 Toast.makeText(this, message, Toast.LENGTH_LONG).show();
  1506.  
  1507.             } catch (Throwable t){
  1508.                 //Toast.makeText(this, "Exception: " + t.toString(), Toast.LENGTH_LONG).show();
  1509.             }*/
  1510.         //}
  1511.         //Display(name+": "+message);
  1512.     }
  1513.  
  1514.     @Override
  1515.     public void onError(String message)  {
  1516.         Display("Error: "+message);
  1517.     }
  1518.  
  1519.     @Override
  1520.     public void onConnectError(final BluetoothDevice device, String message) {
  1521.         Display("Error: "+message);
  1522.         Display("Trying again in 3 sec.");
  1523.         runOnUiThread(new Runnable() {
  1524.             @Override
  1525.             public void run() {
  1526.                 Handler handler = new Handler();
  1527.                 handler.postDelayed(new Runnable() {
  1528.                     @Override
  1529.                     public void run() {
  1530.                         b.connectToDevice(device);
  1531.                     }
  1532.                 }, 2000);
  1533.             }
  1534.         });
  1535.     }
  1536.  
  1537.     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  1538.         @Override
  1539.         public void onReceive(Context context, Intent intent) {
  1540.             final String action = intent.getAction();
  1541.  
  1542.             if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
  1543.                 final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
  1544.                 //Intent intent1 = new Intent(Chat.this, Select.class);
  1545.                 Intent intent1 = new Intent(FFmpegRecordActivity.this, Select.class);
  1546.  
  1547.                 switch (state) {
  1548.                     case BluetoothAdapter.STATE_OFF:
  1549.                         if(registered) {
  1550.                             unregisterReceiver(mReceiver);
  1551.                             registered=false;
  1552.                         }
  1553.                         startActivity(intent1);
  1554.                         finish();
  1555.                         break;
  1556.                     case BluetoothAdapter.STATE_TURNING_OFF:
  1557.                         if(registered) {
  1558.                             unregisterReceiver(mReceiver);
  1559.                             registered=false;
  1560.                         }
  1561.                         startActivity(intent1);
  1562.                         finish();
  1563.                         break;
  1564.                 }
  1565.             }
  1566.         }
  1567.     };
  1568.  
  1569.     private LineDataSet createSet() {
  1570.         LineDataSet set = new LineDataSet(null, "Data");
  1571.         //set.setDrawCubic(boolean enabled)
  1572.         //set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
  1573.         set.setDrawCubic(true);
  1574.         set.setCubicIntensity(0.2f);
  1575.         set.setAxisDependency(YAxis.AxisDependency.LEFT);
  1576.         set.setColor(ColorTemplate.getHoloBlue());
  1577.         set.setCircleColor(ColorTemplate.getHoloBlue());
  1578.         set.setLineWidth(2f);
  1579.         set.setCircleSize(4f);
  1580.         set.setFillAlpha(65);
  1581.         set.setFillColor(ColorTemplate.getHoloBlue());
  1582.         set.setHighLightColor(Color.rgb(244,117,177));
  1583.         set.setValueTextColor(Color.WHITE);
  1584.         set.setValueTextSize(10f);
  1585.  
  1586.         return set;
  1587.     }
  1588.  
  1589.  
  1590. }
Advertisement
Add Comment
Please, Sign In to add comment