1

I try to build a custom video recording app and followed a tutorial on the internet. However I get the problem that the screen goes to black after pressing the start button and nothing else happened. After pressing stop button, I checked the directory where I put the output video. It is there but the size is 0 KB.

I used a surfaceview and here is the xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<TextView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/hello"
   />
<Button
 android:id="@+id/start" 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="- Start Camera Preview -"
   />
<Button
 android:id="@+id/stop" 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="- Stop Camera Preview -"
   />
<SurfaceView
 android:id="@+id/surfaceview" 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
</LinearLayout>

And here is brief code for recording video:

public class CamTestActivity extends Activity implements SurfaceHolder.Callback{
    private static final String TAG = "Camera-Tutorial";

    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private Camera camera;
    private boolean previewRunning;
    private int VIDEO_TYPE = 3;
    private int intVideoIndex = 1;

    private MediaRecorder mediaRecorder;
    private final int maxDurationInMs = 20000;
    private final int videoFramesPerSecond = 20;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.videopreview);

       // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);      
        Button start_video = (Button) findViewById(R.id.start);
        Button stop_video = (Button) findViewById(R.id.stop);


        stop_video.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mediaRecorder.stop();
                camera.lock();
            }
        });

        start_video.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                try {
                    camera.unlock();                   
                    mediaRecorder = new MediaRecorder();
                    mediaRecorder.setCamera(camera);               
                    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

                    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                                                mediaRecorder.setOutputFile(GetOutputMediaFileDir(VIDEO_TYPE,intVideoIndex));
                   mediaRecorder.setVideoFrameRate(1);
                   mediaRecorder.setVideoEncoder(MediaRecorder.AudioEncoder.AAC);
                   mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

                   mediaRecorder.prepare();
                    mediaRecorder.start();
                } catch (IllegalStateException e) {
                    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
                  //  Log.e(TAG,e.getMessage());
                 //   e.printStackTrace();

                } catch (IOException e) {
                    Log.e(TAG,e.getMessage());
                  //  e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
        if (camera != null){
            Camera.Parameters params = camera.getParameters();
            camera.setParameters(params);
        }
        else {
            Toast.makeText(getApplicationContext(), "Camera not available!", Toast.LENGTH_LONG).show();
            finish();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (previewRunning){
            camera.stopPreview();
        }
        Camera.Parameters p = camera.getParameters();
        p.setPreviewSize(width, height);
        camera.setParameters(p);

        try {
            camera.setPreviewDisplay(holder);
            camera.startPreview();
            previewRunning = true;
        }
        catch (IOException e) {
            Log.e(TAG,e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        previewRunning = false;
        camera.release();
    }
 public static String GetOutputMediaFileDir(int fileType, int index){

        String fileDir=null;

          String strIndex = Integer.toString(index);
          if(fileType == 1)
          {
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_MUSIC), "Audio");

        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){

                return null;
            }
        }

          fileDir = mediaStorageDir.getPath() + File.separator +
                  "AUDIO_"+ strIndex + ".mp4";
          }
          if(fileType == 2)
          {
              File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_PICTURES), "Image");

                if (! mediaStorageDir.exists()){
                    if (! mediaStorageDir.mkdirs()){

                        return null;
                    }
                }

                  fileDir = mediaStorageDir.getPath() + File.separator +
                          "IMAGE_"+ strIndex + ".jpeg"; 
          }

          if(fileType == 3)
          {
              File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_MOVIES), "Video");

                if (! mediaStorageDir.exists()){
                    if (! mediaStorageDir.mkdirs()){

                        return null;
                    }
                }

                  fileDir = mediaStorageDir.getPath() + File.separator +
                          "VIDEO_"+ strIndex + ".mp4"; 
          }


       return fileDir;

        }

}

Any ideas of how to solve the problem? Thanks a lot in advance.

Changes that solve the problem:

Firstly I set the video encoder to an audio encoder, this should be changed;

Secondly mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); should be added beforemediaRecorder.prepare()

Then it works properly.

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
Iam619
  • 795
  • 2
  • 12
  • 28

1 Answers1

0

I experienced this issue on an HTC Incredible device, yet it worked perfectly on the 8 others I tested it on. Here is the post the 'solved' that issue:

https://stackoverflow.com/a/9903357/1426565

I narrowed the actual fix down to a specific line:

recorder.setVideoSize(width, height);

The framerate/bitrate settings were irrelevant in the fix, and I'm unsure if using the DEFAULTs for sources, output format, and encoders will change anything, but if you think about it, it shouldn't affect it at all.

These are the other settings I'm using with it (make sure size is set before any Encoder):

    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

    recorder.setPReviewDisplay(surfaceView.getHolder().getSurface())

Also note, in testing yesterday on ICS we encountered an issue where setFrameRate was not supported, as well as setVideoSize was not supported. So, in the fix I'm about to attempt, I'm just going to surround the setVideoSize with a try/catch block, remove setFrameRate, and hope to God that fixes it. If not, I'll probably have to have to just exclude it on certain devices.

Community
  • 1
  • 1
Cruceo
  • 6,763
  • 2
  • 31
  • 52
  • Thank you very much for answers! I noticed that I set the video encoder to an audio encoder. However after I changed the encoder to h264 and frame rate to 24, the application will crash after I press the start button. However if I set the encoder to be H263 and frame rate to be 1, then the screen will freeze after pressing start button and nothing else happened. The video output is in the directory but still 0 KB. I've totally been confused by this. Any help is appreciated. – Iam619 Jun 27 '12 at 16:28
  • I'm literally in the process of still testing this as we speak, but I think I found the specific line that fixes our problem: "recorder.setVideoSize(getMaxSupportedVideoSize().width, getMaxSupportedVideoSize().height);" is absolutely necessary. I removed setVideoFrameRate (as the device controls it based on light anyway) and setVideoEncodingBitRate (as that gets adjusted by the device as well), and now it's working properly on all the devices I'm trying it on. If setVideoSize isn't present, it fails and gives us the issue we run into – Cruceo Jun 27 '12 at 16:40
  • Updated main post with more info – Cruceo Jun 27 '12 at 16:47
  • Thanks a lot! I added the line recorder.setVideoSize and removed setVideoFrameRate and setVideoEncodingBitRate, too. Now after a relatively long responding time of pressing start button, the application doesn't crash! And the output video is finally not 0 KB but 1 KB now (although the device said that I cannot play it for some reasons)~(continued) – Iam619 Jun 27 '12 at 16:59
  • (continued) One thing I should mention is that I replaced the getMaxSupportedVideoSize().width, and .height to two integers (640, 480), since I don't have these two methods. One problem is that the screen seems freezes after the long responding time of start button, did you experience this Cruceo? – Iam619 Jun 27 '12 at 16:59
  • That's really interesting... Is it stopping immediately after starting? And do you have an error log? 640x480 is ok (just make sure your camera preview size is set to that too or you'll get choppy video), but as for it freezing, I never experienced that. You may want to add this at the end before prepare(): recorder.setPreviewDisplay(mPreview.getHolder().getSurface()); – Cruceo Jun 27 '12 at 17:00
  • I tested the program on a sumsung (the one like an ipad) instead of in the emulator. If I run the program in the emulator, it will give a start failed logcat maybe because I didn't connect a camera with the computer. – Iam619 Jun 27 '12 at 17:06
  • Thanks a lot Cruceo! I added the setPReviewDisplay(surfaceView.getHolder().getSurface()) before prepare and now it can work properly! I've been dealing with this problem for a long time and finally it is fixed...... – Iam619 Jun 27 '12 at 17:12
  • Really glad I could help! I added the setPreviewDisplay to the main answer -- (And I would accept an answer so you're more likely to get future help, as people in the SO community seem to heavily frown on users not accepting answers (learned that from experience)) :P – Cruceo Jun 27 '12 at 17:17
  • 1
    yeah I've accepted the answer. I was searching how to accept answers just now :P Turned out to click on the check sign besides the answer~ – Iam619 Jun 27 '12 at 17:22