【问题标题】:Is it possible to record MJPEG directly on android?是否可以直接在 android 上录制 MJPEG?
【发布时间】:2021-07-01 08:30:01
【问题描述】:

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

【问题讨论】:

  • ffmpeg -i input -c copy output
  • 我不明白你的评论。你能详细说明一下吗?
  • 不多赘述。 input 是相机或管道的路径。 -c copy 使用 stream copy 模式。 output 是输出。你的问题细节不多,所以我只是给你一个基本的建议。

标签: android video ffmpeg android-camera codec


【解决方案1】:

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(), 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())}"
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多