├── .gitignore ├── app ├── build.gradle └── src │ ├── libs │ ├── ffmpeg-android-arm.jar │ ├── ffmpeg-android-x86.jar │ ├── javacpp.jar │ └── javacv.jar │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── javacv │ │ └── stream │ │ └── test2 │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ ├── ic_action_search.png │ └── ic_launcher.png │ ├── drawable-mdpi │ ├── ic_action_search.png │ └── ic_launcher.png │ ├── drawable-xhdpi │ ├── ic_action_search.png │ └── ic_launcher.png │ ├── layout │ └── activity_main.xml │ ├── menu │ └── activity_main.xml │ ├── values-large │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── import-summary.txt └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | 217 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 218 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 219 | 220 | # User-specific stuff: 221 | .idea/workspace.xml 222 | .idea/tasks.xml 223 | .idea/dictionaries 224 | .idea/vcs.xml 225 | .idea/jsLibraryMappings.xml 226 | 227 | # Sensitive or high-churn files: 228 | .idea/dataSources.ids 229 | .idea/dataSources.xml 230 | .idea/dataSources.local.xml 231 | .idea/sqlDataSources.xml 232 | .idea/dynamic.xml 233 | .idea/uiDesigner.xml 234 | 235 | # Gradle: 236 | .idea/gradle.xml 237 | .idea/libraries 238 | 239 | # Mongo Explorer plugin: 240 | .idea/mongoSettings.xml 241 | 242 | ## File-based project format: 243 | *.iws 244 | 245 | ## Plugin-specific files: 246 | 247 | # IntelliJ 248 | /out/ 249 | 250 | # mpeltonen/sbt-idea plugin 251 | .idea_modules/ 252 | 253 | # JIRA plugin 254 | atlassian-ide-plugin.xml 255 | 256 | # Crashlytics plugin (for Android Studio and IntelliJ) 257 | com_crashlytics_export_strings.xml 258 | crashlytics.properties 259 | crashlytics-build.properties 260 | fabric.properties 261 | 262 | .idea/ 263 | .gradle/ 264 | *.iml 265 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.example.javacv.stream.test2" 9 | minSdkVersion 16 10 | targetSdkVersion 25 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile 'com.android.support:appcompat-v7:25.3.1' 23 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 24 | 25 | compile 'pub.devrel:easypermissions:0.2.1' 26 | 27 | compile group: 'org.bytedeco', name: 'javacv', version: '1.3.2' 28 | // compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.2.0-1.3', classifier: 'android-arm' 29 | // compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.2.0-1.3', classifier: 'android-x86' 30 | compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.2.1-1.3', classifier: 'android-arm' 31 | compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.2.1-1.3', classifier: 'android-x86' 32 | 33 | 34 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 35 | exclude group: 'com.android.support', module: 'support-annotations' 36 | }) 37 | testCompile 'junit:junit:4.12' 38 | } 39 | -------------------------------------------------------------------------------- /app/src/libs/ffmpeg-android-arm.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/libs/ffmpeg-android-arm.jar -------------------------------------------------------------------------------- /app/src/libs/ffmpeg-android-x86.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/libs/ffmpeg-android-x86.jar -------------------------------------------------------------------------------- /app/src/libs/javacpp.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/libs/javacpp.jar -------------------------------------------------------------------------------- /app/src/libs/javacv.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/libs/javacv.jar -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/javacv/stream/test2/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.javacv.stream.test2; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.pm.ActivityInfo; 6 | import android.graphics.Bitmap; 7 | import android.graphics.Canvas; 8 | import android.hardware.Camera; 9 | import android.media.AudioFormat; 10 | import android.media.AudioRecord; 11 | import android.media.MediaRecorder; 12 | import android.os.Environment; 13 | import android.os.PowerManager; 14 | import android.support.v7.app.AppCompatActivity; 15 | import android.os.Bundle; 16 | import android.util.Log; 17 | import android.view.KeyEvent; 18 | import android.view.SurfaceHolder; 19 | import android.view.SurfaceView; 20 | import android.view.View; 21 | import android.widget.Button; 22 | import android.widget.LinearLayout; 23 | import android.widget.Toast; 24 | 25 | import org.bytedeco.javacv.FFmpegFrameRecorder; 26 | import org.bytedeco.javacv.Frame; 27 | 28 | import java.io.IOException; 29 | import java.nio.ByteBuffer; 30 | import java.nio.ShortBuffer; 31 | 32 | import pub.devrel.easypermissions.EasyPermissions; 33 | 34 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 35 | 36 | private final static String LOG_TAG = "MainActivity"; 37 | 38 | private PowerManager.WakeLock mWakeLock; 39 | 40 | //private String ffmpeg_link = "rtmp://live:live@128.122.151.108:1935/live/test.flv"; 41 | private String ffmpeg_link = Environment.getExternalStorageDirectory() + "/test.flv"; 42 | 43 | private volatile FFmpegFrameRecorder recorder; 44 | boolean recording = false; 45 | long startTime = 0; 46 | 47 | private int sampleAudioRateInHz = 44100; 48 | private int imageWidth = 320; 49 | private int imageHeight = 240; 50 | private int frameRate = 30; 51 | 52 | private Thread audioThread; 53 | volatile boolean runAudioThread = true; 54 | private AudioRecord audioRecord; 55 | private AudioRecordRunnable audioRecordRunnable; 56 | 57 | private CameraView cameraView; 58 | //private IplImage yuvIplimage = null; 59 | private Frame yuvImage; 60 | 61 | private Button recordButton; 62 | private LinearLayout mainLayout; 63 | private boolean init = false; 64 | 65 | @Override 66 | public void onCreate(Bundle savedInstanceState) { 67 | super.onCreate(savedInstanceState); 68 | 69 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 70 | setContentView(R.layout.activity_main); 71 | } 72 | 73 | @Override 74 | protected void onResume() { 75 | super.onResume(); 76 | 77 | boolean hasPermissions = EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA) 78 | && EasyPermissions.hasPermissions(this, Manifest.permission.RECORD_AUDIO) 79 | && EasyPermissions.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); 80 | 81 | if (hasPermissions) { 82 | if (!init) { 83 | initLayout(); 84 | init = true; 85 | } 86 | } else { 87 | Toast.makeText(this, "Please, grant all permissions in app settings", Toast.LENGTH_LONG).show(); 88 | } 89 | 90 | if (mWakeLock == null) { 91 | PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 92 | mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, LOG_TAG); 93 | mWakeLock.acquire(); 94 | } 95 | } 96 | 97 | @Override 98 | protected void onPause() { 99 | super.onPause(); 100 | 101 | if (mWakeLock != null) { 102 | mWakeLock.release(); 103 | mWakeLock = null; 104 | } 105 | } 106 | 107 | @Override 108 | protected void onDestroy() { 109 | super.onDestroy(); 110 | 111 | recording = false; 112 | } 113 | 114 | 115 | private void initLayout() { 116 | 117 | mainLayout = (LinearLayout) this.findViewById(R.id.record_layout); 118 | 119 | recordButton = (Button) findViewById(R.id.recorder_control); 120 | recordButton.setText("Start"); 121 | recordButton.setOnClickListener(this); 122 | 123 | cameraView = new CameraView(this); 124 | 125 | LinearLayout.LayoutParams layoutParam = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); 126 | mainLayout.addView(cameraView, layoutParam); 127 | Log.v(LOG_TAG, "added cameraView to mainLayout"); 128 | } 129 | 130 | private void initRecorder() { 131 | Log.w(LOG_TAG,"initRecorder"); 132 | 133 | 134 | // region 135 | yuvImage = new Frame(imageWidth, imageHeight, Frame.DEPTH_UBYTE, 2); 136 | Log.d(LOG_TAG, "IplImage.create"); 137 | // endregion 138 | 139 | recorder = new FFmpegFrameRecorder(ffmpeg_link, imageWidth, imageHeight, 1); 140 | Log.v(LOG_TAG, "FFmpegFrameRecorder: " + ffmpeg_link + " imageWidth: " + imageWidth + " imageHeight " + imageHeight); 141 | 142 | recorder.setFormat("flv"); 143 | Log.v(LOG_TAG, "recorder.setFormat(\"flv\")"); 144 | 145 | recorder.setSampleRate(sampleAudioRateInHz); 146 | Log.v(LOG_TAG, "recorder.setSampleRate(sampleAudioRateInHz)"); 147 | 148 | // re-set in the surface changed method as well 149 | recorder.setFrameRate(frameRate); 150 | Log.v(LOG_TAG, "recorder.setFrameRate(frameRate)"); 151 | 152 | // Create audio recording thread 153 | audioRecordRunnable = new AudioRecordRunnable(); 154 | audioThread = new Thread(audioRecordRunnable); 155 | } 156 | 157 | // Start the capture 158 | public void startRecord() { 159 | initRecorder(); 160 | 161 | try { 162 | recorder.start(); 163 | startTime = System.currentTimeMillis(); 164 | recording = true; 165 | audioThread.start(); 166 | } catch (FFmpegFrameRecorder.Exception e) { 167 | e.printStackTrace(); 168 | } 169 | } 170 | 171 | public void stopRecord() { 172 | // This should stop the audio thread from running 173 | runAudioThread = false; 174 | 175 | if (recorder != null && recording) { 176 | recording = false; 177 | Log.v(LOG_TAG,"Finishing recording, calling stop and release on recorder"); 178 | try { 179 | recorder.stop(); 180 | recorder.release(); 181 | } catch (FFmpegFrameRecorder.Exception e) { 182 | e.printStackTrace(); 183 | } 184 | recorder = null; 185 | } 186 | } 187 | 188 | @Override 189 | public boolean onKeyDown(int keyCode, KeyEvent event) { 190 | // Quit when back button is pushed 191 | if (keyCode == KeyEvent.KEYCODE_BACK) { 192 | if (recording) { 193 | stopRecord(); 194 | } 195 | finish(); 196 | return true; 197 | } 198 | return super.onKeyDown(keyCode, event); 199 | } 200 | 201 | @Override 202 | public void onClick(View v) { 203 | if (!recording) { 204 | startRecord(); 205 | Log.w(LOG_TAG, "Start Button Pushed"); 206 | recordButton.setText("Stop"); 207 | } else { 208 | stopRecord(); 209 | Log.w(LOG_TAG, "Stop Button Pushed"); 210 | recordButton.setText("Start"); 211 | } 212 | } 213 | 214 | //--------------------------------------------- 215 | // audio thread, gets and encodes audio data 216 | //--------------------------------------------- 217 | class AudioRecordRunnable implements Runnable { 218 | 219 | @Override 220 | public void run() { 221 | // Set the thread priority 222 | android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 223 | 224 | // Audio 225 | int bufferSize; 226 | short[] audioData; 227 | int bufferReadResult; 228 | 229 | bufferSize = AudioRecord.getMinBufferSize(sampleAudioRateInHz, 230 | AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); 231 | audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleAudioRateInHz, 232 | AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 233 | 234 | audioData = new short[bufferSize]; 235 | 236 | Log.d(LOG_TAG, "audioRecord.startRecord()"); 237 | audioRecord.startRecording(); 238 | 239 | // Audio Capture/Encoding Loop 240 | while (runAudioThread) { 241 | // Read from audioRecord 242 | bufferReadResult = audioRecord.read(audioData, 0, audioData.length); 243 | if (bufferReadResult > 0) { 244 | //Log.v(LOG_TAG,"audioRecord bufferReadResult: " + bufferReadResult); 245 | 246 | // Changes in this variable may not be picked up despite it being "volatile" 247 | if (recording) { 248 | try { 249 | // Write to FFmpegFrameRecorder 250 | recorder.recordSamples(ShortBuffer.wrap(audioData, 0, bufferReadResult)); 251 | } catch (FFmpegFrameRecorder.Exception e) { 252 | Log.e(LOG_TAG, e.getMessage()); 253 | e.printStackTrace(); 254 | } 255 | } 256 | } 257 | } 258 | Log.v(LOG_TAG,"AudioThread Finished"); 259 | 260 | /* Capture/Encoding finished, release recorder */ 261 | if (audioRecord != null) { 262 | audioRecord.stop(); 263 | audioRecord.release(); 264 | audioRecord = null; 265 | Log.v(LOG_TAG,"audioRecord released"); 266 | } 267 | } 268 | } 269 | 270 | class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback { 271 | 272 | private boolean previewRunning = false; 273 | 274 | private SurfaceHolder holder; 275 | private Camera camera; 276 | 277 | private byte[] previewBuffer; 278 | 279 | long videoTimestamp = 0; 280 | 281 | Bitmap bitmap; 282 | Canvas canvas; 283 | 284 | public CameraView(Context _context) { 285 | super(_context); 286 | 287 | holder = this.getHolder(); 288 | holder.addCallback(this); 289 | holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 290 | } 291 | 292 | @Override 293 | public void surfaceCreated(SurfaceHolder holder) { 294 | camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); 295 | 296 | try { 297 | camera.setPreviewDisplay(holder); 298 | camera.setPreviewCallback(this); 299 | 300 | Camera.Parameters currentParams = camera.getParameters(); 301 | Log.v(LOG_TAG,"Preview Framerate: " + currentParams.getPreviewFrameRate()); 302 | Log.v(LOG_TAG,"Preview imageWidth: " + currentParams.getPreviewSize().width + " imageHeight: " + currentParams.getPreviewSize().height); 303 | 304 | // Use these values 305 | imageWidth = currentParams.getPreviewSize().width; 306 | imageHeight = currentParams.getPreviewSize().height; 307 | frameRate = currentParams.getPreviewFrameRate(); 308 | 309 | bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ALPHA_8); 310 | 311 | 312 | /* 313 | Log.v(LOG_TAG,"Creating previewBuffer size: " + imageWidth * imageHeight * ImageFormat.getBitsPerPixel(currentParams.getPreviewFormat())/8); 314 | previewBuffer = new byte[imageWidth * imageHeight * ImageFormat.getBitsPerPixel(currentParams.getPreviewFormat())/8]; 315 | camera.addCallbackBuffer(previewBuffer); 316 | camera.setPreviewCallbackWithBuffer(this); 317 | */ 318 | 319 | camera.startPreview(); 320 | previewRunning = true; 321 | } 322 | catch (IOException e) { 323 | Log.v(LOG_TAG,e.getMessage()); 324 | e.printStackTrace(); 325 | } 326 | } 327 | 328 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 329 | Log.v(LOG_TAG,"Surface Changed: width " + width + " height: " + height); 330 | 331 | // We would do this if we want to reset the camera parameters 332 | /* 333 | if (!recording) { 334 | if (previewRunning){ 335 | camera.stopPreview(); 336 | } 337 | 338 | try { 339 | //Camera.Parameters cameraParameters = camera.getParameters(); 340 | //p.setPreviewSize(imageWidth, imageHeight); 341 | //p.setPreviewFrameRate(frameRate); 342 | //camera.setParameters(cameraParameters); 343 | 344 | camera.setPreviewDisplay(holder); 345 | camera.startPreview(); 346 | previewRunning = true; 347 | } 348 | catch (IOException e) { 349 | Log.e(LOG_TAG,e.getMessage()); 350 | e.printStackTrace(); 351 | } 352 | } 353 | */ 354 | 355 | // Get the current parameters 356 | Camera.Parameters currentParams = camera.getParameters(); 357 | Log.v(LOG_TAG,"Preview Framerate: " + currentParams.getPreviewFrameRate()); 358 | Log.v(LOG_TAG,"Preview imageWidth: " + currentParams.getPreviewSize().width + " imageHeight: " + currentParams.getPreviewSize().height); 359 | 360 | // Use these values 361 | imageWidth = currentParams.getPreviewSize().width; 362 | imageHeight = currentParams.getPreviewSize().height; 363 | frameRate = currentParams.getPreviewFrameRate(); 364 | 365 | // Create the yuvIplimage if needed 366 | //yuvIplimage = IplImage.create(imageWidth, imageHeight, IPL_DEPTH_8U, 2); 367 | yuvImage = new Frame(imageWidth, imageHeight, Frame.DEPTH_UBYTE, 2); 368 | //yuvIplimage = IplImage.create(imageWidth, imageHeight, IPL_DEPTH_32S, 2); 369 | } 370 | 371 | @Override 372 | public void surfaceDestroyed(SurfaceHolder holder) { 373 | try { 374 | camera.setPreviewCallback(null); 375 | 376 | previewRunning = false; 377 | camera.release(); 378 | 379 | } catch (RuntimeException e) { 380 | Log.v(LOG_TAG,e.getMessage()); 381 | e.printStackTrace(); 382 | } 383 | } 384 | 385 | @Override 386 | public void onPreviewFrame(byte[] data, Camera camera) { 387 | 388 | if (yuvImage != null && recording) { 389 | videoTimestamp = 1000 * (System.currentTimeMillis() - startTime); 390 | 391 | // Put the camera preview frame right into the yuvIplimage object 392 | //yuvIplimage.getByteBuffer().put(data); 393 | 394 | // region 395 | ((ByteBuffer)yuvImage.image[0].position(0)).put(data); 396 | // endregion 397 | 398 | // FAQ about IplImage: 399 | // - For custom raw processing of data, getByteBuffer() returns an NIO direct 400 | // buffer wrapped around the memory pointed by imageData, and under Android we can 401 | // also use that Buffer with Bitmap.copyPixelsFromBuffer() and copyPixelsToBuffer(). 402 | // - To get a BufferedImage from an IplImage, we may call getBufferedImage(). 403 | // - The createFrom() factory method can construct an IplImage from a BufferedImage. 404 | // - There are also a few copy*() methods for BufferedImage<->IplImage data transfers. 405 | 406 | // Let's try it.. 407 | // This works but only on transparency 408 | // Need to find the right Bitmap and IplImage matching types 409 | 410 | /* 411 | bitmap.copyPixelsFromBuffer(yuvIplimage.getByteBuffer()); 412 | //bitmap.setPixel(10,10,Color.MAGENTA); 413 | 414 | canvas = new Canvas(bitmap); 415 | Paint paint = new Paint(); 416 | paint.setColor(Color.GREEN); 417 | float leftx = 20; 418 | float topy = 20; 419 | float rightx = 50; 420 | float bottomy = 100; 421 | RectF rectangle = new RectF(leftx,topy,rightx,bottomy); 422 | canvas.drawRect(rectangle, paint); 423 | 424 | bitmap.copyPixelsToBuffer(yuvIplimage.getByteBuffer()); 425 | */ 426 | //Log.v(LOG_TAG,"Writing Frame"); 427 | 428 | try { 429 | 430 | // Get the correct time 431 | recorder.setTimestamp(videoTimestamp); 432 | 433 | // Record the image into FFmpegFrameRecorder 434 | //recorder.record(yuvIplimage); 435 | 436 | // region 437 | recorder.record(yuvImage); 438 | // endregion 439 | 440 | } catch (FFmpegFrameRecorder.Exception e) { 441 | Log.v(LOG_TAG,e.getMessage()); 442 | e.printStackTrace(); 443 | } 444 | } 445 | } 446 | } 447 | } 448 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-hdpi/ic_action_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-mdpi/ic_action_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-xhdpi/ic_action_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vanevery/JavaCV_0.3_stream_test/df2f549cc04f7777286b83dfecc1bc690997dd51/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 |