Вопрос

I've got a MediaRecorder recording video, and I'm very confused by the effect of setCaptureRate().

Specifically, I prepare my MediaRecorder as follows:

mMediaRecorder = new MediaRecorder();
mCamera.stopPreview();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.QUALITY_TIME_LAPSE_480P);
mMediaRecorder.setCaptureRate(30f);
mMediaRecorder.setOrientationHint(270);
mMediaRecorder.setOutputFile(...);
mMediaRecorder.setPreviewDisplay(...);
mMediaRecorder.prepare();

I record for five seconds (with a CountDownTimer, but that's irrelevant), and this is the file that gets generated:

$ ffmpeg -i ~/CaptureRate30fps.mp4 
...
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 30.00 (30/1)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/CaptureRate30fps.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 0
    compatible_brands: isom3gp4
    creation_time   : 2013-06-04 00:52:00
  Duration: 00:00:02.59, start: 0.000000, bitrate: 5238 kb/s
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 5235 kb/s, PAR 65536:65536 DAR 3:2, 30 fps, 30 tbr, 90k tbn, 180k tbc
    Metadata:
      creation_time   : 2013-06-04 00:52:00

Note that the Duration is just about 3 seconds. The video also plays much faster, as if it were 5 seconds of video crammed into 3.

Now, if I record by preparing my mediaRecorder exactly as above, but subtracting the setCaptureRate(30f) line, I get a file like this:

$ ffmpeg -i ~/NoSetCaptureRate.mp4 
...
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 90000.00 (180000/2)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/NoSetCaptureRate.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 0
    compatible_brands: isom3gp4
    creation_time   : 2013-06-04 00:50:41
  Duration: 00:00:04.87, start: 0.000000, bitrate: 2803 kb/s
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 2801 kb/s, PAR 65536:65536 DAR 3:2, 16.01 fps, 90k tbr, 90k tbn, 180k tbc
    Metadata:
      creation_time   : 2013-06-04 00:50:41

Note that the Duration is as expected, about 5 seconds. The video also plays at a normal speed.

I'm using setCaptureRate(30f) because 30 frames per second is the value of my CamcorderProfile's videoFrameRate. On my Galaxy Nexus S2 (4.2.1), omitting setCaptureRate() is fine, but when I tested on a Galaxy Nexus S3 (4.1.1), omitting setCaptureRate() results in the ever-helpful "start failed -22" error when I called mMediaRecorder.start().

So, what am I missing? I thought that the capture rate and the video frame rate were independent, but it's clear that they're not. Is there a way to determine programmatically what I need to set the capture rate at in order to determine that my video plays back at 1x speed?

Это было полезно?

Решение

(This is a summary of the resolution from the comments on the original question)

The problem may be that directly using the QUALITY_TIME_LAPSE_480P profile influences playback rates, since time lapses are implicitly not a 1x playback rate.

Furthermore, if the reason you're using that profile is to prevent audio from being recorded when using QUALITY_480P (since time lapses don't record audio), you may want to instead call CamcorderProfile.get(QUALITY_480P) and set video parameters on the MediaRecorder manually based on the profile, without calling MediaRecorder.setProfile directly. A MediaRecorder that doesn't have any audio parameters set shouldn't in theory record any audio.

Другие советы

According to documentation, setCaptureRate(double fps) is used to set time lapse recording, with audio ignored. It is most useful if you want less fps than the system can actually provide. You ask more fps than the system can provide, here is a quote from developer.android.com/reference:

Note that the recorder cannot guarantee that frames will be captured at the given rate due to camera/encoder limitations. However it tries to be as close as possible.

What your code does not call, is setVideoFrameRate(int rate). I believe that using this function, your recording will be fixed.

You are correct.I will give you correct answer.i have faced same situation.start failed-22 belongs to frame rate.hence capture rate which you are giving is not in the range of device. use getSupportedPreviewFpsRange() first to determine device fps range and then set accordingly.You can use PREVIEW_FPS_MAX_INDEX and PREVIEW_FPS_MIN_INDEX for maximum and minimum fFps.

use following code it will give result multiplied by 1000 i.e if frame rate is 5 ,it will return 5000.

Camera.Parameters camParameter = camera.getParameters();
    List<int[]> frame = camParameter.getSupportedPreviewFpsRange();
        Iterator<int[]> 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 < i; j++) {
                sb.append(tmpRate[j] + ", ");
            }
            Log.d(VTAG, sb.toString());
        }
    }

for more check here :http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewFpsRange()

EDIT: In android developer document. It is mentioned that setCaptureRate() Sets video frame capture rate. This can be used to set a different video frame capture rate than the recorded video's playback rate. This method also sets the recording mode to time lapse. Since it also sets recording mode to time lapse so check video after removing setprofile QUALITY_TIME_LAPSE_480P to any other supported normal profile such as QUALITY_480P or make pure custom mediaRecorder setting by setting video size and other.It may help you.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top