title: .setPreviewFpsRange(): Having problems updating frames per second in camera .setParameters()
body: <p><strong>UPDATED 28 October 2015 to reflect current progress.</strong> 
  I have an application that allows the user to set camera parameters for Motion JPEG recording, create an MJPEG file, and then the user can modify those settings and create another file with the updated settings. I am having a problem updating the frames per second setting when the initial value is something other than 30 FPS. When the initial value is 30 FPS, I can update to a different FPS level and sucessfully record a video AT THAT LEVEL. However, I cannot update from a level that is not equal to 30FPS to another FPM level. I get a crash with LogCat showing a problem at </p>
  
  <p>camera.setParameters(parameters);</p>
  
  <p>Full LogCat of error is below,</p>
  
  <pre><code>10-26 20:27:36.414: E/AndroidRuntime(2275): FATAL EXCEPTION: main
  10-26 20:27:36.414: E/AndroidRuntime(2275): java.lang.RuntimeException: setParameters failed
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.hardware.Camera.native_setParameters(Native Method)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.hardware.Camera.setParameters(Camera.java:1333)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at net.blepsias.riverwatch.RiverWatch.setCamera(RiverWatch.java:191)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at net.blepsias.riverwatch.RiverWatch.onClick(RiverWatch.java:167)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.view.View.performClick(View.java:3514)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.view.View$PerformClick.run(View.java:14111)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.os.Handler.handleCallback(Handler.java:605)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.os.Handler.dispatchMessage(Handler.java:92)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.os.Looper.loop(Looper.java:137)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at android.app.ActivityThread.main(ActivityThread.java:4429)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at java.lang.reflect.Method.invokeNative(Native Method)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at java.lang.reflect.Method.invoke(Method.java:511)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
  10-26 20:27:36.414: E/AndroidRuntime(2275):     at dalvik.system.NativeStart.main(Native Method)
  </code></pre>
  
  <p>Checking the LogCat cited line 5 and 6, these correspond to:</p>
  
  <pre><code>(191) camera.setParameters(parameters);
  (167) setCamera(camera);
  </code></pre>
  
  <p>Below is the application. I'll also include the layout .xml file for reference, as well as a screenshot for grounding.</p>
  
  <p><strong>RiverWatch.java</strong></p>
  
  <pre><code>public class RiverWatch extends Activity implements OnClickListener, SurfaceHolder.Callback, Camera.PreviewCallback {
  public static final String LOGTAG = "VIDEOCAPTURE";
  
  String szBoundaryStart = "\r\n\r\n--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length: ";
  String szBoundaryDeltaTime = "\r\nDelta-time: 110";
  String szBoundaryEnd = "\r\n\r\n";
  
  private SurfaceHolder holder;
  private Camera camera;  
  private CamcorderProfile camcorderProfile;
  
  Spinner spinnerCamcorderProfile;
  public TextView tvFramesPerSecond, tvJpegQuality, tvSegmentDuration;
  
  boolean bRecording = false;
  boolean bPreviewRunning = false;
  
  int intFramesPerSecond = 30000; //this is 30fps...mult by 1,000
  int intJpegQuality=50; //must be above 20
  int intSegmentDuration=10;
  boolean ckbxRepeat=false;
  
  byte[] previewCallbackBuffer;
  
  File mjpegFile;
  FileOutputStream fos;
  BufferedOutputStream bos;
  Button btnStartRecord, btnStopRecord, btnExit, btnChange;
  
  Camera.Parameters parameters;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  
      Date T = new Date();
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
      String szFileName = "videocapture-"+sdf.format(T)+"-";
  
      try {       
          mjpegFile = File.createTempFile(szFileName, ".mjpeg", Environment.getExternalStorageDirectory());               
      } catch (Exception e) {
          finish();
      }
  
      requestWindowFeature(Window.FEATURE_NO_TITLE);
      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
              WindowManager.LayoutParams.FLAG_FULLSCREEN);
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
      setContentView(R.layout.main);
  
      tvFramesPerSecond = (TextView) this.findViewById(R.id.textboxframespersecondxml);
      int iFPS = intFramesPerSecond/1000;
      String szFPS = Integer.toString(iFPS);
      tvFramesPerSecond.setClickable(true);       
      tvFramesPerSecond.setText(szFPS);
      tvFramesPerSecond.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
              getSupportedPreviewFpsRange();
          }
      });
  
      tvJpegQuality = (TextView) this.findViewById(R.id.textboxJpegQualityxml);
      String szJpegQuality = Integer.toString(intJpegQuality);
      tvJpegQuality.setText(szJpegQuality);
  
      tvSegmentDuration = (TextView) this.findViewById(R.id.textboxSegmentDurationxml);
      String szSegmentDuration = Integer.toString(intSegmentDuration);
      tvSegmentDuration.setText(szSegmentDuration);
  
      btnStartRecord = (Button) this.findViewById(R.id.StartRecordButton);
      btnStartRecord.setOnClickListener(this);
  
      btnStopRecord = (Button) this.findViewById(R.id.StopRecordButton);
      btnStopRecord.setOnClickListener(this);
  
      btnExit = (Button) this.findViewById(R.id.ExitButton);
      btnExit.setOnClickListener(this);
  
      btnChange = (Button) this.findViewById(R.id.ChangeButton);
      btnChange.setOnClickListener(this);
  
      camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_480P);
      SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
      holder = cameraView.getHolder();
      holder.addCallback(this);
      holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  
      cameraView.setClickable(true);
      cameraView.setOnClickListener(this);
  }
  
  @Override
  public void onClick(View v) {
          switch (v.getId()) {
          case R.id.StartRecordButton:
              try {
                  fos = new FileOutputStream(mjpegFile);
                  bos = new BufferedOutputStream(fos);
                  bRecording = true;
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              }
              Toast.makeText(this, "Recording started.", Toast.LENGTH_SHORT).show();
              break;
          case R.id.StopRecordButton:     
              try {
                  bos.flush();
                  bos.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              Toast.makeText(this, "Recording stopped.", Toast.LENGTH_SHORT).show();
              break;      
  
          case R.id.ChangeButton: 
              //Frames Per Second- expressed x1000 in the function                
              String szFPS=tvFramesPerSecond.getText().toString();
              int iFPS = Integer.parseInt(szFPS);
              intFramesPerSecond = iFPS *1000;
  
              //Jpeg quality- cant be &lt;20 or &gt;100, checks this and populates field with entered or corrected value.
              String szJpegQuality=tvJpegQuality.getText().toString();
              int intJpegQualityTemp = Integer.parseInt(szJpegQuality);
              if (intJpegQualityTemp &lt; 21){//...can't be less than 21
                  intJpegQuality = 21;
              }else if(intJpegQualityTemp &gt; 100){//can't be greater than 100
                   intJpegQuality = 100;
              }else{ //quality is between 21 and 100...
                  intJpegQuality = intJpegQualityTemp;
              }
              szJpegQuality = Integer.toString(intJpegQuality);
              tvJpegQuality.setText(szJpegQuality);   
  
              //Segment duration
              String szSegmentDuration=tvSegmentDuration.getText().toString();
              intSegmentDuration = Integer.parseInt(szSegmentDuration);
  
              releaseCamera();
              setCamera(camera);      
  
              camera.startPreview();  
              Toast.makeText(this, "Change button pressed.", Toast.LENGTH_SHORT).show();
              break;
  
          case R.id.ExitButton:
              System.exit(0);
              break;
          }
      }
  
  public void releaseCamera(){
      camera.stopPreview();
     //camera.release();  //...cause crash
     //camera = null;
  }
  public void setCamera(Camera camera){
      Camera.Parameters parameters=camera.getParameters();
      parameters.setPreviewFpsRange(intFramesPerSecond, intFramesPerSecond);//note: This is fps x 1000 (!)
      parameters.setPreviewSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
      Log.v(LOGTAG,"FPS: " + parameters.getSupportedPreviewFpsRange());
      camera.setParameters(parameters);
  }
  
  
  public void getSupportedPreviewFpsRange(){
  /****************************************************************
   * getSupportedPreviewFpsRange()- Returns specified frame rate 
   * (.getSupportedPreviewFpsRange()) to log file and also displays 
   * as toast message.
   ****************************************************************/              
  Camera.Parameters camParameter = camera.getParameters();
  List&lt;int[]&gt; frame = camParameter.getSupportedPreviewFpsRange();
      Iterator&lt;int[]&gt; supportedPreviewFpsIterator = frame.iterator();
      while (supportedPreviewFpsIterator.hasNext()) {
          int[] tmpRate = supportedPreviewFpsIterator.next();
          StringBuffer sb = new StringBuffer();
          sb.append("SupportedPreviewRate: ");
          for (int i = tmpRate.length, j = 0; j &lt; i; j++) {
              sb.append(tmpRate[j] + ", ");
          }
          Log.d(LOGTAG, "FPS6: " + sb.toString());
          Toast.makeText(this, "FPS = "+sb.toString(), Toast.LENGTH_SHORT).show();
      }//*****************end getSupportedPreviewFpsRange()**********************                                                 
  }   
  
  public void surfaceCreated(SurfaceHolder holder) {
      camera = Camera.open();
  }
  @SuppressLint("NewApi")
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
      if (!bRecording) {
          if (bPreviewRunning = true){
              camera.stopPreview();
          } try {
              parameters = camera.getParameters();
              parameters.setPreviewSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
              parameters.setPreviewFpsRange(intFramesPerSecond, intFramesPerSecond);//note: This is fps x 1000 (!)
              //p.setPreviewFrameRate(intFramesPerSecond);
              camera.setParameters(parameters);
              camera.setPreviewDisplay(holder);               
              camera.setPreviewCallback(this);
              camera.setDisplayOrientation(90);
              camera.startPreview();
              bPreviewRunning = true;
          }
          catch (IOException e) {
              e.printStackTrace();
          }   
      }
  }
  
  public void surfaceDestroyed(SurfaceHolder holder) {
      if (bRecording) {
          bRecording = false;
          try {
              bos.flush();
              bos.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      bPreviewRunning = false;
      camera.release();
      finish();
  }   
  
  public void onPreviewFrame(byte[] b, Camera c) {
      if (bRecording) {
          // Assuming ImageFormat.NV21
          if (parameters.getPreviewFormat() == ImageFormat.NV21) {
              try {
                  YuvImage im = new YuvImage(b, ImageFormat.NV21, parameters.getPreviewSize().width, parameters.getPreviewSize().height, null);
                  Rect r = new Rect(0,0,parameters.getPreviewSize().width,parameters.getPreviewSize().height);
                  ByteArrayOutputStream jpegByteArrayOutputStream = new ByteArrayOutputStream();
                  im.compressToJpeg(r, intJpegQuality, jpegByteArrayOutputStream);//note: qual = 20 or less doesn't work.
                  byte[] jpegByteArray = jpegByteArrayOutputStream.toByteArray();
                  byte[] boundaryBytes = (szBoundaryStart + jpegByteArray.length + szBoundaryDeltaTime + szBoundaryEnd).getBytes();
                  bos.write(boundaryBytes);                                       
                  bos.write(jpegByteArray);
                  bos.flush();
                  //bos.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          } else {
              Log.v(LOGTAG,"NOT THE RIGHT FORMAT");
          }
      }
  }
  @Override
  public void onConfigurationChanged(Configuration conf){
      super.onConfigurationChanged(conf); 
    } 
  }
  </code></pre>
  
  <p><strong>Layout main.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" &gt;
  &lt;LinearLayout
       android:orientation="horizontal"
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content"&gt;
  &lt;Button
      android:id="@+id/StartRecordButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Start Recording" /&gt;    
  &lt;Button
      android:id="@+id/StopRecordButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Stop Recording" /&gt;   
    &lt;Button
      android:id="@+id/ChangeButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="50dip"
      android:text="Reset settings" /&gt; 
  &lt;/LinearLayout&gt;
  &lt;LinearLayout
       android:orientation="horizontal"
       android:layout_width="match_parent" 
       android:layout_height="wrap_content"
       android:gravity="right"&gt;
   &lt;TextView
      style="@style/myStyle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Frames/second:" /&gt;
  &lt;EditText 
          android:id="@+id/textboxframespersecondxml"
          android:editable="true"
          style="@style/myStyle"
          android:layout_width="wrap_content" 
          android:layout_height="wrap_content"
          android:gravity="right"
          android:text="0"
          android:layout_marginRight="10dip"/&gt;
  &lt;/LinearLayout&gt;
  &lt;LinearLayout
       android:orientation="horizontal"
       android:layout_width="match_parent" 
       android:layout_height="wrap_content"
       android:gravity="right"&gt;
   &lt;TextView
      style="@style/myStyle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="JPEG image quality:" /&gt;
  &lt;EditText 
          android:id="@+id/textboxJpegQualityxml"
          android:editable="true"
          style="@style/myStyle"
          android:layout_width="wrap_content" 
          android:layout_height="wrap_content"
          android:gravity="right"
          android:text="0"
          android:layout_marginRight="10dip"/&gt;
  &lt;/LinearLayout&gt;
  &lt;LinearLayout
  android:orientation="horizontal"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"&gt;
  &lt;TextView
      style="@style/myStyle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="10dip"
      android:text="Camcorder profile: " /&gt;
  &lt;LinearLayout
       android:orientation="horizontal"
       android:layout_width="match_parent" 
       android:layout_height="wrap_content"
       android:gravity="right"&gt;
   &lt;TextView
      style="@style/myStyle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Segment duration (file length):" /&gt;
  &lt;EditText 
          android:id="@+id/textboxSegmentDurationxml"
          android:editable="true"
          style="@style/myStyle"
          android:layout_width="wrap_content" 
          android:layout_height="wrap_content"
          android:gravity="right"
          android:text="0"
          android:layout_marginRight="10dip"/&gt;
   &lt;TextView
      style="@style/myStyle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text=" minutes" /&gt;
  &lt;/LinearLayout&gt;
  &lt;LinearLayout
      android:orientation="horizontal"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="right" &gt;     
  &lt;CheckBox
      android:id="@+id/repeat"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Repeat" /&gt;
  &lt;Button
      android:id="@+id/ExitButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Exit Application" /&gt;
  &lt;/LinearLayout&gt;
  &lt;SurfaceView
      android:id="@+id/CameraView"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" /&gt;
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p><strong>Screenshot:</strong> Showing fields, buttons, and surface config</p>
  
  <p><a href="https://i.stack.imgur.com/nnTel.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/nnTel.png" alt=""></a></p>
  
  <p><strong>Resolution:</strong> It appears that much of the above erratic behaviour may be related to the primary testing device which is a Panasonic Toughpad JT-B1. Running </p>
  
  <pre><code>.getSupportedPreviewFpsRange(); 
  </code></pre>
  
  <p>on this device returns a range of 8,000-30,000 fps. However, many values in this range result in crashes, and some values outside of this range appear to work fine. Testing a Samsung S4 Active resulted in none of these inconsistencies, with all of the values in the returned range (4,000 - 30,000) working fine, and no tested values outside of this range demonstrating any functionality as expected.</p>