是否可以直接在 android 上录制 MJPEG?

问题描述

是否可以将安卓相机的视频直接录制为 MJPEG?出于质量目的,我对 MJPEG 感兴趣。我不想通过认的 android 设置录制视频然后转换为 MJPEG,而是直接从相机设备转换为 MJPEG。这可能吗?我找不到任何信息表明这是可能的。

解决方法

Kotlin 中的代码。

您只需要通过 setRepeatingRequest 获取捕获请求上的连续图像。 调用 takeMJPEG,true 开始,false 停止。

用 GOM 播放器打开生成的文件。我已经测试了实现。


    private val takeMJPEGSemaphore  = Semaphore(1)

    var mjpegBufferStream: BufferedOutputStream? = null
    var mjpegFileStream: FileOutputStream? = null
    var mjpegRecording = false


    override fun takeMJPEG(start: Boolean) {
        Log.i(TAG,"takeMJPEG start:$start")
        if (start) {
            takeMJPEGSemaphore.acquire()
            mjpegRecording = true
            val mjpegOutputFile = createFile(context,"mjpeg")
            mjpegFileStream = FileOutputStream(mjpegOutputFile)
            mjpegBufferStream = BufferedOutputStream(mjpegFileStream)
            // Clear imageReader
            var image: Image? = null
            do {
                image?.close()
                image = imageReader.acquireNextImage()
            } while (image != null)
            session.stopRepeating()
            session.setRepeatingRequest(captureRequest.build(),null,cameraHandler)
            var count = 0
            var initialTime: Long = 0
            imageReader.setOnImageAvailableListener({ reader ->
                image = reader.acquireNextImage()
                if (count == 0) {
                    initialTime = image!!.timestamp
                }
                count++
                val buffer = image?.planes?.get(0)?.buffer
                val bytes = ByteArray(buffer!!.remaining()).apply { buffer.get(this) }
                mjpegBufferStream!!.write(bytes)
                mjpegBufferStream!!.flush()
                if (!mjpegRecording) {
                    imageReader.setOnImageAvailableListener(null,null)
                    session.stopRepeating()
                    session.setRepeatingRequest(previewRequest.build(),cameraHandler)
                    // Save the mjpeg file
                    mjpegBufferStream?.flush()
                    mjpegBufferStream?.close()
                    val finalTime = image!!.timestamp
                    Log.i(TAG,"saved mjpeg file with fps = ${count / ((finalTime - initialTime) / 1000000000.0)}")
                    takeMJPEGSemaphore.release()
                }
                image?.close()
            },imageReaderHandler)
        } else {
            mjpegRecording = false
            takeMJPEGSemaphore.acquire()
            takeMJPEGSemaphore.release()
        }
    }


        private fun createFile(context: Context,extension: String): File {
            val dir = File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM),"Camera")
            if (!dir.exists()) {
                dir.mkdirs()
            }
            return File.createTempFile(createFileName(),".$extension",dir)
        }
        private fun createFileName(): String {
            val sdf = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS",Locale.US)
            return "IMG_${sdf.format(Date())}"
        }