Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CamcorderProfile.QUALITY_HIGH resolution produces green flickering video

I haven't found any explanation for this so far. Basically I have a video recording class which works splendidly when setVideoSize() is set to 720 x 480 on my Samsung Galaxy S2.

I want it to record in the highest possible resolution so using CamcorderProfile.QUALITY_HIGH I can get the various highest quality recording properties and set them within my class. This works for file format, video frame rate, encoders and bit rate, however when I attempt to set the video size to the width and height returned by the CamcorderProfile (1920 x 1080), the video recorded is just a green flicker.

I noticed if I changed 720 x 480 to 720 x 481 it did the same thing. Therefore I can only assume this happens when the resolution isn't supported by the phone. However, the camcorder the phone came with can record in 1920 x 1080 and it produces an excellent recording.

I can only assume with such a high resolution I need to set some other parameters differently, but I just cant figure out what they might be.

Has anyone else had this problem?

Thanks in advance for any replies.

like image 451
William Stewart Avatar asked Aug 29 '11 02:08

William Stewart


3 Answers

I came across this question trying to solve the same problem.

A solution is given over on xda developer http://forum.xda-developers.com/showthread.php?t=1104970&page=8. It seems that you need to set an obscure parameter "cam_mode" for high definition recording to work:

camera = Camera.open();
Camera.Parameters param = camera.getParameters();
param.set( "cam_mode", 1 );     
camera.setParameters( param );

In mediarecorder, you can then use

mediarecorder.setVideoSize(1920, 1080);

although this will now also work:

mediarecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

(The latter seems to have a video bitrate of 20Mb/s, so you might want to take that down a bit!) I found that I didn't have to set the preview size to 1920x1080.

(edit) You also need to set

parame.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);

or

param.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);

otherwise you get a delay of a few seconds before the camera starts!

As to why Samsung has implemented the Camera in this way, I have no idea. It's certainly not developer friendly!

like image 78
SGS2camera Avatar answered Nov 19 '22 02:11

SGS2camera


Here is how I managed to make this work on Samsung Galaxy S2. The critical point here is to set the same resolution both in camera parameters and recorder video size. Also, already mentioned 'cam_mode' hack is required. So, I allowed a user to select from three quality modes: low (800x480), medium(1280x720), and high(1920x1080):

enum InternalCameraQuality {
    LOW, MEDIUM, HIGH
}

and when creating/populating camera and recorder I did

// signature types are irrelevant here
File start(DeviceHandler handler, FileHelper fh) throws IOException {
    file = fh.createTempFile(".mp4");

    camera = Camera.open();
    setCameraParameters(camera);
    camera.setPreviewDisplay(getHolder());
    camera.unlock();

    recorder = new MediaRecorder();
    recorder.setCamera(camera);
    setRecorderParameters(recorder);

    recorder.prepare();
    recorder.start();

    return file;
}

void setCameraParameters(Camera camera) {
    Camera.Parameters param = camera.getParameters();

    // getParams() simply returns some field holding configuration parameters
    // only the 'quality' parameter is relevant here
    if (getParams().quality != InternalCameraQuality.LOW) {
        // Samsung Galaxy hack for HD video
        param.set("cam_mode", 1);
    }

    Pair<Integer, Integer> resolution = getResolution(getParams().quality);
    param.setPreviewSize(resolution.first, resolution.second);
    param.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);

    camera.setParameters(param);
}

void setRecorderParameters(MediaRecorder recorder) {
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    Pair<Integer, Integer> resolution = getResolution(getParams().quality);

    CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
    profile.videoFrameWidth = resolution.first;
    profile.videoFrameHeight = resolution.second;
    recorder.setProfile(profile);

    recorder.setOutputFile(file.getAbsolutePath());
    recorder.setPreviewDisplay(getHolder().getSurface());
}

Pair<Integer, Integer> getResolution(InternalCameraQuality quality) {
    final int width, height;
    switch (quality) {
        case LOW:
            width = 800;
            height = 480;
            break;
        case MEDIUM:
            width = 1280;
            height = 720;
            break;
        case HIGH:
            width = 1920;
            height = 1080;
            break;
        default:
            throw new IllegalArgumentException("Unknown quality: " + quality.name());
    }
    return Pair.create(width, height);
}

Note that you must use the 'cam_mode' hack only for medium and high quality, otherwise green flickering will appear in low quality mode. Also you may wish to customize some other profile settings if you need.

Hope, that helped.

like image 8
Tvaroh Avatar answered Nov 19 '22 02:11

Tvaroh


        List<Size> ls = parameters.getSupportedPreviewSizes();
        Size size = ls.get(1);
        sizes 1 ----------960 720
        sizes 2 ----------800 480
        sizes 3 ----------720 480
        sizes 5 -----------640 384
        sizes 6 ----------576 432
        sizes 7 ----------480 320

this are the list of sizes and more in android.

like image 1
user1628121 Avatar answered Nov 19 '22 01:11

user1628121