Android 中的 FFMPEG 视频录制正在获取绿色锁存器的覆盖

FFMPEG Video Recording in Android getting overlay of Green latches

我使用 FFMPEG 和 OpenCV 将视频播放器集成到 Android 应用程序中。

构建 Gradle:-

 compile('org.bytedeco:javacv-platform:1.4') {
    exclude group: 'org.bytedeco.javacpp-presets'
}
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.0-1.4'
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.4.1-1.4'
compile files('libs/ffmpeg-android-arm.jar')
compile files('libs/ffmpeg-android-x86.jar')
compile files('libs/opencv-android-arm.jar')
compile files('libs/opencv-android-x86.jar')

我已将 'jniLibs' 包含在 'main' 文件夹中 'armeabi,amreabi-v7a, x86' 文件夹的。

我可以打开相机并录制视频。

视频O/P未按预期播放,音频质量良好。请看下图。

我用于集成的代码:https://github.com/CrazyOrr/FFmpegRecorder

提前致谢!!

我使用 SurfaceView 找到了解决方法。检查我的工作代码。

public class SurfaceViewVideo extends Activity implements MediaPlayer.OnPreparedListener{

private Camera myCamera;
private MyCameraSurfaceView myCameraSurfaceView;
private MediaRecorder mediaRecorder;
private int currentCameraId=1;
ImageView myButton,switchCamera;
SurfaceHolder surfaceHolder;
boolean recording;
boolean isVideoStopped;
private MediaPlayer mediaPlayer;
private SurfaceView playSurfaceView;
private SurfaceHolder playSurfaceHolder;
private FrameLayout videoView;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    recording = false;
    isVideoStopped = false;
    setContentView(R.layout.activity_surface_view_video);
    switchCamera = (ImageView)findViewById(R.id.switchCamera);
    playSurfaceView = (SurfaceView)findViewById(R.id.playSurface);
    playSurfaceHolder = playSurfaceView.getHolder();
    videoView = (FrameLayout)findViewById(R.id.videoview);
    //Get Camera for preview
    myCamera = getCameraInstance();
    if(myCamera == null){
        Toast.makeText(this,
                "Fail to get Camera",
                Toast.LENGTH_LONG).show();
    }

    myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
    FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
    myCameraPreview.addView(myCameraSurfaceView);

    myButton = (ImageView)findViewById(R.id.mybutton);
    myButton.setOnClickListener(myButtonOnClickListener);
    switchCamera.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onCameraChange();
        }
    });
}

Button.OnClickListener myButtonOnClickListener
        = new Button.OnClickListener(){

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(!isVideoStopped) {
            if (recording) {
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object

                myButton.setImageResource(R.drawable.ic_play);
                isVideoStopped = true;
                videoView.setVisibility(View.GONE);
                myCameraSurfaceView.setVisibility(View.GONE);
                playSurfaceView.setVisibility(View.VISIBLE);
            } else {

                //Release Camera before MediaRecorder start
                releaseCamera();

                if (!prepareMediaRecorder()) {
                    Toast.makeText(SurfaceViewVideo.this,
                            "Fail in prepareMediaRecorder()!\n - Ended -",
                            Toast.LENGTH_LONG).show();
                }

                mediaRecorder.start();
                recording = true;
                myButton.setImageResource(R.drawable.ic_stop_white_24px);
            }
        }else{
            if(mediaPlayer==null) {
                mediaPlayer = new MediaPlayer();
                try {
                    mediaPlayer.setDisplay(playSurfaceHolder);
                    mediaPlayer.setDataSource("/sdcard/myvideo.mp4");
                    mediaPlayer.prepare();
                    mediaPlayer.setOnPreparedListener(SurfaceViewVideo.this);
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else{
                mediaPlayer.start();
            }
        }
    }};

private Camera getCameraInstance(){
    // TODO Auto-generated method stub
    Camera c = null;
    try {
        c = Camera.open(1); // attempt to get a Camera instance
        c.setDisplayOrientation(90);
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

public void onCameraChange() {

    myCamera.stopPreview();
    myCamera.release();
    if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    }
    else {
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    }
    myCamera = Camera.open(currentCameraId);
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
    int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;
    switch (rotation) {
        case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
        case Surface.ROTATION_90: degrees = 90; break; //Landscape left
        case Surface.ROTATION_180: degrees = 180; break;//Upside down
        case Surface.ROTATION_270: degrees = 270; break;//Landscape right
    }
    int rotate = (info.orientation - degrees + 360) % 360;

    //STEP #2: Set the 'rotation' parameter
    Camera.Parameters params = myCamera.getParameters();
    params.setRotation(rotate);
    try {
        myCamera.setPreviewDisplay(myCameraSurfaceView.getHolder());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    myCamera.setParameters(params);
    myCamera.setDisplayOrientation(90);
    myCamera.startPreview();
}
private boolean prepareMediaRecorder(){
    myCamera = getCameraInstance();
    mediaRecorder = new MediaRecorder();

    myCamera.unlock();
    mediaRecorder.setCamera(myCamera);

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));

    mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
    mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
    mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M

    mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
    mediaRecorder.setOrientationHint(270);

    try {
        mediaRecorder.prepare();
    } catch (IllegalStateException e) {
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        releaseMediaRecorder();
        return false;
    }
    return true;

}

@Override
protected void onPause() {
    super.onPause();
    releaseMediaRecorder();       // if you are using MediaRecorder, release it first
    releaseCamera();              // release the camera immediately on pause event
    releaseMediaPlayer();
}

private void releaseMediaRecorder(){
    if (mediaRecorder != null) {
        mediaRecorder.reset();   // clear recorder configuration
        mediaRecorder.release(); // release the recorder object
        mediaRecorder = null;
        myCamera.lock();           // lock camera for later use
    }
}

private void releaseCamera(){
    if (myCamera != null){
        myCamera.release();        // release the camera for other applications
        myCamera = null;
    }
}

public void releaseMediaPlayer(){
    if(mediaPlayer!=null){
        mediaPlayer.release();
        mediaPlayer = null;
    }
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
    mediaPlayer.start();
}

public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

    private SurfaceHolder mHolder;
    private Camera mCamera;

    public MyCameraSurfaceView(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        // supported preview sizes
        mSupportedPreviewSizes = myCamera.getParameters().getSupportedPreviewSizes();

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                               int height) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
            // ignore: tried to stop a non-existent preview
        }

        // make any resize, rotate or reformatting changes here

        // start preview with new settings
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
            mCamera.setParameters(parameters);
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }
}

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio=(double)h / w;

    if (sizes == null) return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

}