如何在 android.. 中的视频中添加过滤器?

How to add filter on video in android..?

如何在录制时以及保存在 android 后对视频添加 过滤

mediaRecorder = new MediaRecorder();

mCamera.unlock();
mediaRecorder.setCamera(mCamera);

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

mediaRecorder.setProfile(
    CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)
);
mediaRecorder.setVideoEncodingBitRate(6000000);

demoVideoFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videokit/";
demoVideoPath = demoVideoFolder + "in.mp4";

File storagePath2 = new File(demoVideoFolder);
storagePath2.mkdir();

mediaRecorder.setOutputFile("/sdcard/videokit/in.mp4");
rotateBackVideo(mediaRecorder);

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

我想在使用 MediaRecorder 录制时在我的视频中添加多个滤镜,并在保存视频后添加滤镜。如何实现第二种情况..?

您可以同时使用 openCVFFmpeg 来达到此目的。有关详细信息,请参阅此 question。 此外,这里是如何快速启动 openCV ,尝试 this

还有一个 ffmpeg github 库 here

public class CameraPreview1 extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    String filter_effect;

    public CameraPreview1(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // create the surface and start camera preview
            if (mCamera == null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException e) {
            Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    @SuppressWarnings("deprecation")
    public void refreshCamera(Camera camera,String effect) {
        filter_effect=effect;
        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
        }
        // set preview size and make any resize, rotate or
        // reformatting changes here
        // start preview with new settings
        setCamera(camera);
        try {
            Camera.Parameters params = mCamera.getParameters();
            if(filter_effect.equals("none"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_NONE);
            }
            else if(filter_effect.equals("mono"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_MONO);
            }
            else if(filter_effect.equals("negative"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
            }
            else if(filter_effect.equals("solarize"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);
            }
            else if(filter_effect.equals("sepia"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_SEPIA);
            }
            else if(filter_effect.equals("posterize"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_POSTERIZE);
            }
            else if(filter_effect.equals("whiteboard"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_WHITEBOARD);
            }
            else if(filter_effect.equals("blackboard"))
            {
                params.setColorEffect(Camera.Parameters.EFFECT_BLACKBOARD);
            }
            else if(filter_effect.equals("aqua"))
            {
                params.setColorEffect(Camera.Parameters.EFFECT_AQUA);
            }
            mCamera.setParameters(params);
            mCamera.setPreviewDisplay(mHolder);

            mCamera.setDisplayOrientation(90);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

        refreshCamera(mCamera,filter_effect);
    }

    public void setCamera(Camera camera) {
        //method to set a camera instance
        mCamera = camera;
         Camera.Parameters params = camera.getParameters();
            if (params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            } else {
                //Choose another supported mode
            }
            camera.setParameters(params);
    }

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

    }
}


Class mainActivity

package com.wlc.primetime.camera;

import io.vov.utils.Log;

import java.io.File;
import java.io.IOException;

//import com.google.android.gms.internal.lv;
import com.netcompss.ffmpeg4android.GeneralUtils;
import com.netcompss.ffmpeg4android.Prefs;
import com.netcompss.loader.LoadJNI;
import com.wlc.primetime.R;
import com.wlc.primetime.Events.EventCreateActivity;
import com.wlc.primetime.Events.EventDetailActivity;
import com.wlc.primetime.campus.PostMemoriesActivity2;
import com.wlc.primetime.campus.PostMemoriesActivity3;
import com.wlc.primetime.utils.Common;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.provider.MediaStore;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

public class main_activity extends Activity implements OnClickListener {
    private Camera mCamera;
    private CameraPreview1 mPreview;
    private MediaRecorder mediaRecorder;
    private Button capture, switchCamera;
    private Context myContext;
    private LinearLayout cameraPreview;
    private boolean cameraFront = false;
    RadioGroup rg_filter;
    RadioButton rg_none, rg_mono, rg_negative;
    private TextView tv_appHeader_right = null, tv_timer = null,
            tv_appHeader_left = null, tv_camera_flash = null,
            tv_camera_video = null, tv_camera_capture;
    private ImageView iv_camera_change = null, iv_camera_gallery = null;
    String effect;
    int count = 0;
    Runnable r = null;
    ImageView iv_header_left;
    ImageView iv_appHeader_title;
    String camera_state;
    String workFolder = null;
    String demoVideoFolder = null;
    String demoVideoPath = null;
    String vkLogPath = null;
    private boolean commandValidationFailedFlag = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.video_preview_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        count = 0;
        View customHeaderView = Common
                .getActionBarCustomView(video_preview_post.this);

        iv_header_left = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_left);
        iv_header_left.setImageResource(R.drawable.ic_back);
        iv_header_left.setVisibility(View.VISIBLE);
        iv_header_left.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                finish();
            }
        });

        ImageView iv_header_right = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_right);
        iv_header_right.setImageResource(R.drawable.ic_profile_poster_edit);
        iv_header_right.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

            }
        });

        iv_appHeader_title = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_title);
        iv_appHeader_title.setImageResource(R.drawable.ic_camera_change);
        iv_appHeader_title.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (!recording) {
                    int camerasNumber = Camera.getNumberOfCameras();
                    if (camerasNumber > 1) {
                        // release the old camera instance
                        // switch camera, from the front and the back and vice
                        // versa

                        releaseCamera();
                        chooseCamera();
                    } else {
                        Toast toast = Toast.makeText(myContext,
                                "Sorry, your phone has only one camera!",
                                Toast.LENGTH_LONG);
                        toast.show();
                    }
                }

            }
        });

        Intent in = getIntent();
        effect = in.getStringExtra("effect");

        iv_camera_gallery = (ImageView) findViewById(R.id.iv_camera_gallery);

        tv_timer = (TextView) findViewById(R.id.tv_timer);
        tv_camera_capture = (TextView) findViewById(R.id.tv_camera_capture);
        tv_camera_capture.setTextSize(TypedValue.COMPLEX_UNIT_SP, 35);
        tv_camera_video = (TextView) findViewById(R.id.tv_camera_video);
        tv_camera_video.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45);
        // set last taken image from gallery
        setLastTakenImage(iv_camera_gallery);

        iv_camera_gallery.setOnClickListener(this);
        tv_camera_capture.setOnClickListener(this);
        tv_camera_video.setOnClickListener(this);

        Common.setAwasomeFontFamily(this, tv_camera_video);
        Common.setAwasomeFontFamily(this,
                (TextView) findViewById(R.id.tv_camera_capture));

        int screenWidth = Common.getScreenWidth(this);

        cameraPreview = (LinearLayout) findViewById(R.id.camera_preview_ll);

        myContext = this;
        initialize();
    }

    private int findFrontFacingCamera() {
        camera_state = "front";
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                cameraId = i;
                cameraFront = true;
                break;
            }
        }
        return cameraId;
    }

    private int findBackFacingCamera() {
        camera_state = "back";
        int cameraId = -1;
        // Search for the back facing camera
        // get the number of cameras
        int numberOfCameras = Camera.getNumberOfCameras();
        // for every camera check
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                cameraId = i;
                cameraFront = false;
                break;
            }
        }
        return cameraId;
    }

    public void onResume() {
        super.onResume();
        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext,
                    "Sorry, your phone does not have a camera!",
                    Toast.LENGTH_LONG);
            toast.show();
            finish();
        }
        if (mCamera == null) {
            // if the front facing camera does not exist
            if (findFrontFacingCamera() < 0) {
                Toast.makeText(this, "No front facing camera found.",
                        Toast.LENGTH_LONG).show();
                switchCamera.setVisibility(View.GONE);
            }
            mCamera = Camera.open(findBackFacingCamera());
            mPreview.refreshCamera(mCamera, effect);
        }
    }

    public void initialize() {
        // cameraPreview = (LinearLayout) findViewById(R.id.camera_preview_ll);

        mPreview = new CameraPreview1(myContext, mCamera);
        // mPreview.setRotation(90);
        cameraPreview.addView(mPreview);
    }

    public void chooseCamera() {
        // if the camera preview is the front
        if (cameraFront) {
            int cameraId = findBackFacingCamera();
            if (cameraId >= 0) {
                // open the backFacingCamera
                // set a picture callback
                // refresh the preview

                mCamera = Camera.open(cameraId);
                // mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera, effect);
            }
        } else {
            int cameraId = findFrontFacingCamera();
            if (cameraId >= 0) {
                // open the backFacingCamera
                // set a picture callback
                // refresh the preview

                mCamera = Camera.open(cameraId);
                // mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera, effect);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // when on Pause, release camera in order to be used from other
        // applications
        releaseCamera();
    }

    private boolean hasCamera(Context context) {
        // check if the device has camera
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            return true;
        } else {
            return false;
        }
    }

    boolean recording = false;

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

    private boolean prepareMediaRecorder() {

        mediaRecorder = new MediaRecorder();

        mCamera.unlock();
        mediaRecorder.setCamera(mCamera);

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

        mediaRecorder.setProfile(CamcorderProfile
                .get(CamcorderProfile.QUALITY_LOW));
        // mediaRecorder.setVideoEncodingBitRate(690000);
        mediaRecorder.setVideoEncodingBitRate(6000000);
        // mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        // mediaRecorder.setOutputFile("/sdcard/Movie.mp4");

        demoVideoFolder = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/videokit/";
        demoVideoPath = demoVideoFolder + "in.mp4";
        // Toast.makeText(getApplicationContext(), ""+demoVideoFolder,
        // 56).show();

        File storagePath2 = new File(demoVideoFolder);
        storagePath2.mkdir();

        mediaRecorder.setOutputFile("/sdcard/videokit/in.mp4");
        rotateBackVideo(mediaRecorder);

        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();

        } catch (IOException e) {
            releaseMediaRecorder();

        }

        return true;

    }

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    private void setLastTakenImage(ImageView iv_gallary_picker) {
        String[] projection = new String[] {
                MediaStore.Images.ImageColumns._ID,
                MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATE_TAKEN,
                MediaStore.Images.ImageColumns.MIME_TYPE };
        final Cursor cursor = getApplicationContext().getContentResolver()
                .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, null, null,
                        MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");

        // Put it in the image view
        if (cursor.moveToFirst()) {
            String imageLocation = cursor.getString(1);
            File imageFile = new File(imageLocation);
            if (imageFile.exists()) {
                Bitmap bm = BitmapFactory.decodeFile(imageLocation);
                iv_gallary_picker.setImageBitmap(bm);
            }
        }
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if (v.getId() == R.id.tv_camera_video) {
            if (count == 0) {
                iv_header_left.setEnabled(false);
                iv_appHeader_title.setEnabled(false);
                tv_camera_capture.setVisibility(View.GONE);
                iv_camera_gallery.setVisibility(View.GONE);
                tv_camera_video.setTextColor(Color.RED);

                count = 1;
                tv_timer.setVisibility(View.VISIBLE);
                if (count != 11) {
                    tv_timer.setText("00:00:" + count);
                }

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

                    final Handler handler = new Handler();

                    r = new Runnable() {
                        public void run() {
                            // tv.append("Hello World");
                            Log.d("count" + count, "ok...");
                            if (count > 11) {

                                if (mediaRecorder != null) {

                                    // count=0;01
                                    try {
                                        mediaRecorder.stop(); // stop the
                                                                // recording
                                        releaseMediaRecorder();
                                        handler.removeCallbacks(r);

                                        workFolder = getApplicationContext()
                                                .getFilesDir()
                                                .getAbsolutePath()
                                                + "/";
                                        Log.i(Prefs.TAG,
                                                "workFolder (license and logs location) path: "
                                                        + workFolder);
                                        vkLogPath = workFolder + "vk.log";
                                        Log.i(Prefs.TAG,
                                                "vk log (native log) path: "
                                                        + vkLogPath);

                                        GeneralUtils
                                                .copyLicenseFromAssetsToSDIfNeeded(
                                                        video_preview_post.this,
                                                        workFolder);
                                        GeneralUtils
                                                .copyDemoVideoFromAssetsToSDIfNeeded(
                                                        video_preview_post.this,
                                                        demoVideoFolder);
                                        int rc = GeneralUtils.isLicenseValid(
                                                getApplicationContext(),
                                                workFolder);

                                        if (GeneralUtils
                                                .checkIfFileExistAndNotEmpty(demoVideoPath)) {
                                            new TranscdingBackground(
                                                    video_preview_post.this)
                                                    .execute();
                                        } else {
                                            Toast.makeText(
                                                    getApplicationContext(),
                                                    demoVideoPath
                                                            + " not found",
                                                    Toast.LENGTH_LONG).show();
                                        }

                                    } catch (Exception e) {
                                        // handler.removeCallbacks(r);
                                        // Intent in =new
                                        // Intent(getApplicationContext(),
                                        // PostMemoriesActivity3.class);
                                        // in.putExtra("PATH_MEMORIES_IMG",
                                        // "video");
                                    }

                                }
                            }
                            if (count <= 10) {
                                tv_timer.setText("00:00:" + count);
                            }
                            count++;
                            handler.postDelayed(this, 1000);
                        }
                    };

                    if (count == 1) {
                        mediaRecorder.start();
                    }
                    handler.postDelayed(r, 0);

                    recording = true;
                }
            }
        } else if (R.id.tv_camera_capture == v.getId()) {
            Intent in = new Intent(getApplicationContext(),
                    CameraFragmentActivity.class);
            startActivity(in);
        }
    }

    public MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {

        /**
         * Define Orientation of video in here, if in portrait mode, use value =
         * 90, if in landscape mode, use value = 0
         */

        int rotation = 0;

        if (camera_state.equals("back")) {
            rotation = 0;
            // Toast.makeText(getApplicationContext(), "front", 45).show();
        } else {
            rotation = 180;
            // Toast.makeText(getApplicationContext(), "back", 45).show();
        }

        switch (rotation) {
        case 0:
            mMediaRecorder.setOrientationHint(90);
            break;
        case 90:
            mMediaRecorder.setOrientationHint(180);
            break;
        case 180:
            mMediaRecorder.setOrientationHint(270);
            break;
        case 270:
            mMediaRecorder.setOrientationHint(0);
            break;
        }

        return mMediaRecorder;
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        Intent in = new Intent(getApplicationContext(),
                CameraFragmentActivity.class);
        finish();
        startActivity(in);

        // super.onBackPressed();
    }

    class TranscdingBackground extends AsyncTask<String, Integer, Integer> {

        ProgressDialog progressDialog;
        Activity _act;

        public TranscdingBackground(Activity act) {
            _act = act;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = new ProgressDialog(_act);
            progressDialog.setMessage("Compressing...");
            progressDialog.show();

        }

        protected Integer doInBackground(String... paths) {
            Log.i(Prefs.TAG, "doInBackground started...");

            // delete previous log
            GeneralUtils.deleteFileUtil(workFolder + "/vk.log");

            PowerManager powerManager = (PowerManager) _act
                    .getSystemService(Activity.POWER_SERVICE);
            WakeLock wakeLock = powerManager.newWakeLock(
                    PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
            Log.d(Prefs.TAG, "Acquire wake lock");
            wakeLock.acquire();

            // /////////// Set Command using code (overriding the UI EditText)
            // /////
            String commandStr = "ffmpeg -y -i /sdcard/videokit/in.mp4 -strict experimental -s 320x240 -r 30 -aspect 3:4 -ab 48000 -ac 2 -ar 22050 -vcodec mpeg4 -b 2097152 /sdcard/videokit/Movie.mp4";// videokit/
            // String[] complexCommand = {"ffmpeg", "-y" ,"-i",
            // "/sdcard/videokit/in.mp4","-strict","experimental","-s",
            // "160x120","-r","25", "-vcodec", "mpeg4", "-b", "150k",
            // "-ab","48000", "-ac", "2", "-ar", "22050",
            // "/sdcard/videokit/out.mp4"};
            // /////////////////////////////////////////////////////////////////////

            LoadJNI vk = new LoadJNI();
            try {

                // complex command
                // vk.run(complexCommand, workFolder, getApplicationContext());

                vk.run(GeneralUtils.utilConvertToComplex(commandStr),
                        workFolder, getApplicationContext());
                GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder);

            } catch (Throwable e) {
                Log.e(Prefs.TAG, "vk run exeption.", e);
            } finally {
                if (wakeLock.isHeld())
                    wakeLock.release();
                else {
                    Log.i(Prefs.TAG,
                            "Wake lock is already released, doing nothing");
                }
            }
            Log.i(Prefs.TAG, "doInBackground finished");
            return Integer.valueOf(0);
        }

        protected void onProgressUpdate(Integer... progress) {
        }

        @Override
        protected void onCancelled() {
            Log.i(Prefs.TAG, "onCancelled");
            // progressDialog.dismiss();
            super.onCancelled();
        }

        @Override
        protected void onPostExecute(Integer result) {
            Log.i(Prefs.TAG, "onPostExecute");
            progressDialog.dismiss();
            super.onPostExecute(result);

            // finished Toast
            String rc = null;
            if (commandValidationFailedFlag) {
                rc = "Command Vaidation Failed";
            } else {
                rc = GeneralUtils.getReturnCodeFromLog(vkLogPath);
            }
            final String status = rc;
            video_preview_post.this.runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(video_preview_post.this, status,
                            Toast.LENGTH_LONG).show();

                    // demoVideoPath = demoVideoFolder + "Movie.mp4";

                    if (status.equals("Transcoding Status: Failed")) {
                        Toast.makeText(
                                video_preview_post.this,
                                "Check: " + vkLogPath
                                        + " for more information.",
                                Toast.LENGTH_LONG).show();
                    } else {
                        Intent in = new Intent(getApplicationContext(),
                                PostMemoriesActivity3.class);
                        in.putExtra("PATH_MEMORIES_IMG", "video");
                        startActivity(in);
                    }
                }
            });
        }
    }
}

从 Android 4.3 开始,您可以使用 Surface 作为编码器的输入。 here

因此您可以使用 GLSurfaceView 并使用片段着色器应用滤镜。

您可以在这里找到一些很好的例子。also help this link