34

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.

William Stewart
  • 801
  • 1
  • 14
  • 27
  • what bout the video encoding format? which one did you set and what did the default app set it to? You might also want to check out the output format as well.. – bluefalcon Aug 29 '11 at 11:06
  • Hey Ravi, I checked out the encoding format. The highest format is H264 which is what it attempts to use, this produces the green flickering. Using H263 stops the green flickering but produces a much lower quality video, significantly lower than a 720 x 480 resolution video. As for the output format, I'll have a look at that and see if it gets it working. Cheers. – William Stewart Aug 29 '11 at 11:30
  • I just tried changing the output format, but it didn't help. 3gpp did the same thing and any other format caused a force close. – William Stewart Aug 29 '11 at 11:54
  • I was going through [this](http://developer.android.com/reference/android/media/CamcorderProfile.html) it says you can only get the profile. Are you settings these parameters on the camera? – bluefalcon Aug 29 '11 at 11:56
  • 1
    The actual resolution seems to be - 1920 x 1088. Can check what resolutions the camera supports? And the set the resolution from that list which is closest to 1080p? – bluefalcon Aug 29 '11 at 11:57
  • No I'm setting the parameters on the MediaRecorder. I haven't used setProfile, instead I used CamcorderProfile cp = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH) then I set each parameter of MediaRecorder separately referencing cp. This way I can find out exactly which setting is messing it up. – William Stewart Aug 29 '11 at 11:59
  • I didn't realise it was 1088. Anyway that hasn't worked :P still produces a green flickering video. – William Stewart Aug 29 '11 at 12:01
  • No what I am trying to say is that your phone might have a different resolution when it says 1080p. So call this [getSupportedVideoSizes](http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedVideoSizes()) API and use the one closest to 1080p, it need not be 1088 :) . It seems to me that the issue is with the resolution since you are setting the rest of the params based on what you get from `get`. that's all I could think of, maybe someone else knows the answer, +1 to bump the ques up the unanswered list :) – bluefalcon Aug 29 '11 at 12:09
  • Ahhh right I get you, I'll give that a go and see what resolutions it returns. Cheers for the help Ravi. – William Stewart Aug 29 '11 at 12:11
  • Hmmm it seems that getSupportedVideoSizes is only available in Android 3.0. First of it means I cant test it on my Galaxy S2 and it means it will drastically reduce the amount of people that can download it. Is there any other method which finds Video sizes similar to getSupportedPictureSizes? – William Stewart Aug 29 '11 at 12:31
  • Still haven't found a solution to this, anyone have any other ideas? – William Stewart Aug 29 '11 at 22:08
  • I seem to recall having issues when the preview aspect ratio was wrong. I ended up digging deep into the Camera/camcorder that is in the Android source and ended up borrowing a lot of their setup/teardown. – Steve Pomeroy Oct 13 '11 at 05:44
  • Thanks for the comment Steve. So the size of the video preview can make a difference to the file that is output? How did you manage to fix this in the end? – William Stewart Oct 13 '11 at 11:41
  • 1
    Hi Will, I downloaded a couple of video recording apps on my Galaxy S2 and all of them produces something like what you've described when set to high setting. it looks like there are many small screens that are tiled and its mostly green with some patches of purple. In one of the apps, it has an "override resolution (Galaxy SII)" option and that allows ontly up to 720p recording, as already mentioned. My friend has a Nexus S, and he has no problems with the app. It cant record in 1080p though. Im beginning to think its an S2/1080p problem? – Mel Oct 18 '11 at 05:44
  • Thanks Mel, I tested it on other devices and as you said it does seem to work, however on my Galaxy S II The highest resolution I can record in without producing the green and purple video is 720 x 480. 1280 x 720 (720p) doesn't seem to work for me either, along with 1920 x 1080 (1080p). Are you saying your Galaxy S II can record using these other camcorder apps at 1280 x 720 and produce a normal video? – William Stewart Oct 19 '11 at 13:30
  • So has anyone found a solution to this problem? not being able to record in Full HD in code on a device that can record in Full HD seems crazy... – Ants Apr 04 '12 at 05:40

5 Answers5

20

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!

SGS2camera
  • 246
  • 3
  • 6
  • Great find! I'll be sure to check this solution out soon and see how it works. Cheers. – William Stewart Mar 07 '12 at 15:21
  • I've just tried this but so far no luck. setting cam_mode makes the preview flicker and recording fails completely. (that is with using setProfile(). – Ants Apr 02 '12 at 21:29
  • I've only recently had the time to check this out and it seems so far it works nicely. On the SGS2 using set("cam_mode", 1) does seem to put it into a HD record mode and as you mentioned using focus mode INFINITY (I use infinity as it doesn't require a high min SDK version). Do you know if it is necessary to set cam_mode to something else when working with anything lower than 1920 x 1080? – William Stewart Jun 07 '12 at 18:45
  • The cam_mode trick worked for me too. Many thanks.However, having set that I found camera snapshots were then corrupted on the S2 (when previously they weren't). I'm still looking into this. Also, I didn't find there was a need for setFocusMode. Will do more testing to check this out. Thanks for the help! – darrenp Feb 21 '13 at 14:54
  • This works great on Samsung Galaxy S2 2.3 but seems to be crashing on 4.0 - any suggestions? Reducing the quality works fine – vkislicins Jun 11 '15 at 19:58
8

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.

Tvaroh
  • 6,255
  • 4
  • 45
  • 54
  • 1
    For some reason 800x480 mode no longer works on Galaxy S II and Android 4. Just replace 800 with 640 and it's okay again. – Tvaroh Nov 08 '12 at 09:23
  • 1
    where is the getParams() method? – Tom Nov 06 '13 at 10:14
  • 1
    Tom H, you don't need it - it's my app specific method which contains user defined settings. Quality is amongst them. – Tvaroh Nov 06 '13 at 10:18
  • I gotcha! I've just has a mission getting this working. Wish I had seen your answer beforehand... saved a day or 2 ;-) – Tom Nov 06 '13 at 10:34
1
        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.

user1628121
  • 65
  • 1
  • 1
  • 4
1

Ok, I tested many variants and the only Version wich works well on real Devices is:

CamcorderProfile camcorderProfile    = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);

// THREE_GPP works well but only on Phones            
//  camcorderProfile.fileFormat = MediaRecorder.OutputFormat.THREE_GPP;

// so better you use MPEG_4 for most Devices and PC
camcorderProfile.fileFormat = MediaRecorder.OutputFormat.MPEG_4;
camcorderProfile.videoCodec = MediaRecorder.VideoEncoder.MPEG_4_SP;

mrec.setProfile(camcorderProfile);
Ingo
  • 4,676
  • 1
  • 25
  • 22
0

I've experienced similar problems like this in the past. What you're doing seems to be fine but here are a few suggestions that might help to debug the problem:

Ensure you are selecting a supported resolution

int cameraId = 0; // using back facing camera
Camera camera = Camera.open(cameraId);
Camera.Parameters cameraParams = camera.getParameters();
List<Camera.Size> supportedPreviewSizes = cameraParams.getSupportedPreviewSizez();

// find suitable Camera preview size from list and set your CamcorderProfile to use that new size

After you've located a suitable preview size be sure to reset your SurfaceView -- you will need to resize it to accommodate the change in aspect ratio

MediaRecorder API uses the SurfaceView so if your surface view isn't configured correctly it will result in the green flicker you're seeing

Ensure you are using a video bit rate that can support the new resolution -- try bumping the video bit rate to double what it was originally set to (*note this drastically effects your output filesize)

CamcorderProfile.QUALITY_HIGH returns the highest possible supported camera resolution. Ensure you are using the correct camera id (front vs. back) -- maybe the back facing camera supports 1080p but the front facing camera does not?

Hope the tips help!

jagsaund
  • 2,289
  • 18
  • 16
  • So are you saying the size of the SurfaceView preview will have an affect on the final video that is output? Also the bit rate is configured using CamcorderProfile.QUALITY_HIGH as well so it should be the highest bit rate supported. Thanks for the help jagsaund, I will mess around with the SurfaceView sizes and see what happens. – William Stewart Oct 24 '11 at 09:43