How to get GPUVideo Android filter on VideoView?

94 Views Asked by At

I am trying to build a project that allows users to enter a video(via their gallery or recording) and apply filters to that video via GPUVideo library but I can't manage to apply filters to the videos it doesn't change anything about it. Should I use something else then URI for playing the video or change the library that I am using? Here is my code:

FilterFragment

class FilterFragment : Fragment() {

    private lateinit var binding: FragmentFilterBinding
    private val viewModel: FilterViewModel by viewModels()
    private val TAG = "FilterFragment"

    //Fields
    private lateinit var filteredVid: VideoView
    private lateinit var saveBtn: FloatingActionButton
    private lateinit var filterOptions: ChipGroup

    private lateinit var sourceVideoUri: Uri


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentFilterBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initializeFields()



    }

    private fun initializeFields() {

        filteredVid = binding.videoView
        saveBtn = binding.floatingActionButton
        filterOptions = binding.chipGroup
        // Get the URI of the video from the arguments
        sourceVideoUri = arguments?.getString("videoUri")!!.toUri()
        // Creating temp file to reference path
        val contentResolver = requireContext().contentResolver
        val inputStream = contentResolver.openInputStream(sourceVideoUri)
        val tempFile = createTempFile("temp", null, requireContext().cacheDir)
        tempFile.outputStream().use { outputStream ->
            inputStream?.copyTo(outputStream)
        }
        applyFilter(GlBilateralFilter(), tempFile.path)
        // Set the video URI as the data source for the VideoView
        Log.d(TAG,"Before start")
        filteredVid.setVideoURI(sourceVideoUri)

        // Start playing the video
        filteredVid.start()
        Log.d(TAG,"After start")




    }
    private fun applyFilter(appliedFilter: GlFilter,filePath : String) {
        lifecycleScope.launch {
            GPUMp4Composer(filePath, filePath)
                .rotation(Rotation.ROTATION_90)
                .size(540, 960)
                .fillMode(FillMode.PRESERVE_ASPECT_FIT)
                .filter(appliedFilter)
                .listener(object : GPUMp4Composer.Listener {
                    override fun onProgress(progress: Double) {
                        Log.d(TAG, "onProgress = $progress")
                    }

                    override fun onCompleted() {
                        Log.d(TAG, "onCompleted()")
//                    Toast.makeText(context, "codec complete path =$filePath.toString()", Toast.LENGTH_SHORT).show()

                    }

                    override fun onCanceled() {
                        Log.d(TAG, "onCanceled")
                    }

                    override fun onFailed(exception: Exception?) {
                        Log.e(TAG, "onFailed()", exception)
                    }
                })
                .start()

        }
    }

}

Input Fragment

class InputFragment : Fragment() {

    //Binding
    private lateinit var binding: FragmentInputBinding

    //Fields
    private lateinit var recordBtn: Button
    private lateinit var chooseBtn: Button
    private lateinit var filterBtn: Button
    private lateinit var previewVid: VideoView


    private lateinit var viewModel: InputViewModel

    private var videoInputUri: Uri? = null

    private val videoChooser =
        registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            uri?.let {
                videoInputUri = it
                prepareVideoInput(it)
                previewVid.visibility = View.VISIBLE
            }
        }

    private val videoRecorder =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.resultCode == Activity.RESULT_OK) {
                result.data?.data?.let { uri ->
                    videoInputUri = uri
                    viewModel.selectVideoUri(uri)
                }
                previewVid.visibility = View.VISIBLE
            }
        }


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentInputBinding.inflate(inflater, container, false)

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initializeFields()

    }

    private fun initializeFields() {
        viewModel = ViewModelProvider(this)[InputViewModel::class.java]

        chooseBtn = binding.chooseVideoBtn
        recordBtn = binding.recordVideoBtn
        filterBtn = binding.animateBtn
        previewVid = binding.videoView

        chooseBtn.setOnClickListener {
            launchVideoChooser()
        }

        recordBtn.setOnClickListener {
            launchVideoRecorder()
        }

        filterBtn.setOnClickListener {
            if (previewVid.isVisible) {
                val videoUri = videoInputUri.toString()
                val bundle = bundleOf("videoUri" to videoUri)
                binding.root.findNavController().navigate(R.id.action_inputFragment_to_filterFragment,bundle)
            }
            else
                Toast.makeText(requireActivity(),"Enter a Video!",Toast.LENGTH_SHORT).show()
        }

        viewModel.selectedVideoUri.observe(viewLifecycleOwner) { uri ->
            videoInputUri = uri
            if (videoInputUri != null) {
                prepareVideoInput(videoInputUri!!)
            }
        }

    }

    private fun launchVideoChooser() {
        videoChooser.launch("video/*")
    }

    private fun launchVideoRecorder() {
        val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
        videoRecorder.launch(intent)
    }


    private fun prepareVideoInput(videoUri: Uri) {
        previewVid.setVideoURI(videoUri)
        previewVid.start()
    }




    companion object {
        private const val REQUEST_VIDEO_RECORDER = 2
    }


}
0

There are 0 best solutions below