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

标签 android video ffmpeg android-camera codec

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

最佳答案

Kotlin 中的代码。
您只需在捕获请求上通过 setRepeatingRequest 获取连续图像。
使用 true 开始调用 takeMJPEG,以 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(), null, 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())}"
        }

关于android - 是否可以直接在 android 上录制 MJPEG?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66953685/

相关文章:

android - 如何在 Android 3.x 或 4.x 上以编程方式配置静态 IP 地址、网络掩码、网关

Android 相机 - 我们可以从全屏中截取图像的一部分吗

c++ - OpenCV 视频编辑?

java - ffmpeg 加入两个 mp4 视频一个接一个

video - 为什么 ffmpeg 报告不同的持续时间?

用于启动/停止 ffmpeg x11grab 的 bash 脚本

android - 在 LogCat 中显示 Android 线程 ID

android - 如何在Android Studio中成功同步?

Drupal youtube 集成

video - HLS - ffmpeg 失败,无法为输出文件 #0 写入 header (编解码器参数不正确?): No such file or directory