bytedeco/javacv

how to use hw accelerator with FFMpegFrameRecorder

オープン

#2,046 opened on 2023/06/23

 (6 件のコメント) (0 件のリアクション) (0 人の担当者)Java (1,583 件のフォーク)batch import
enhancementhelp wantedquestion

Repository metrics

Stars
 (6,985 個のスター)
PR merge metrics
 (30d に merged PR はありません)

説明

I try to use mobile hardware accelerator with FFMpegFrameRecorder, but software only is used :

private fun initFFMpegRecorder() { ffmpeg_link = File(StorageUtils.createPhoneVideoFileName(context))

    yuvImage = Frame(1920, 1080, Frame.DEPTH_UBYTE, 2)
    Log.i(LOG_FFMPEG, "create yuvImage")

    ffMpegFrameRecorder = FFmpegFrameRecorder(
        ffmpeg_link,
        1920,
        1080,
        1
    )
    ffMpegFrameRecorder?.format = "mkv"

    ffMpegFrameRecorder?.sampleRate = sampleAudioRateInHz
    ffMpegFrameRecorder?.audioBitrate = 128 * 1024
    ffMpegFrameRecorder?.audioCodec = avcodec.AV_CODEC_ID_AAC

    ffMpegFrameRecorder?.setVideoMetadata("rotate", "90")

    ffMpegFrameRecorder?.frameRate = 30.toDouble()
    ffMpegFrameRecorder?.videoBitrate = 6 * 1000 * 1024
    ffMpegFrameRecorder?.gopSize = 30
    ffMpegFrameRecorder?.isInterleaved = true
    ffMpegFrameRecorder?.videoCodec = avcodec.AV_CODEC_ID_H264
    ffMpegFrameRecorder?.pixelFormat = avutil.AV_PIX_FMT_YUV420P

    ffMpegFrameRecorder?.videoCodecName = "h264_mediacodec"

    ffMpegFrameRecorder?.timestamp = 1000 * (System.currentTimeMillis() - startTime)
    ffMpegFrameRecorder?.setVideoOption("preset", "ultrafast")
    ffMpegFrameRecorder?.setVideoOption("tune", "zerolatency")

    Log.i(
        LOG_FFMPEG,
        "recorder video initialize success"
    )

    audioRecordRunnable = AudioRecordRunnable()
    audioThread = Thread(audioRecordRunnable)
    runAudioThread = true
    Log.i(
        LOG_FFMPEG,
        "recorder audio initialize success"
    )
}

fun startRec() { initFFMpegRecorder()

        try {
            val avCodec: AVCodec? = avcodec.avcodec_find_encoder_by_name("h264_mediacodec")
            if (avCodec != null) {
                Log.i(
                    "SUPPORT_ENCODER_TELEPHONE",
                    "avCodec != null, " + avCodec.name().getString()
                        .toString() + "/ " + avCodec.long_name().getString()
                )
            } else {
                Log.i("SUPPORT_ENCODER_TELEPHONE", "avCodec == null")
            }

            ffMpegFrameRecorder?.start()
            startTime = System.currentTimeMillis()
            recording = true
            audioThread?.start()
            isRecordingVideo.set(true)
            Log.d(LOG_FFMPEG, "FFMpeg launched")
        } catch (e: FFmpegFrameRecorder.Exception) {
            e.printStackTrace()
        }

}

i can get rawVideo here (i am using Camera2 API and ImageReader) like this :

imageReader = ImageReader.newInstance(1920, 1080, ImageFormat.YUV_420_888, 1) imageReader?.setOnImageAvailableListener( mOnImageAvailableListener, mBackgroundHandler )

private val mOnImageAvailableListener = OnImageAvailableListener { p0 ->

            val image = p0.acquireNextImage()

            /* get video data */
            if (yuvImage != null && recording) {
                (yuvImage!!.image[0].position(0) as ByteBuffer).put(image!!.planes[0].buffer)

                val bytes = bzyuvUtil?.preHandleYUV420(image, false, 0)
                val newBytes = ByteArray(1920 * 1080 * 3 / 2)
                BZYUVUtil.yuvI420ToNV21(bytes, newBytes, 1920, 1080)
                (yuvImage!!.image[0].position(0) as ByteBuffer).put(newBytes)

                try {
                    Log.v(
                        LOG_FFMPEG,
                        "Writing Frame Telephone"
                    )
                    val t = 1000 * (System.currentTimeMillis() - startTime)
                    if (t > ffMpegFrameRecorder?.getTimestamp()!!) {
                        ffMpegFrameRecorder?.setTimestamp(t)
                    }

                    ffMpegFrameRecorder?.record(yuvImage)
                    isRecordingVideo.set(true)
                } catch (e: FFmpegFrameRecorder.Exception) {
                    Log.v(
                        LOG_FFMPEG,
                        e.message!!
                    )
                    e.printStackTrace()
                }
            }

            image?.close()
        }
    }
}

build.gradle : task javacppExtract(type: Copy) { dependsOn configurations.javacpp

from { configurations.javacpp.collect { zipTree(it) } }
include "lib/**"
into "$buildDir/javacpp/"
android.sourceSets.main.jniLibs.srcDirs += ["$buildDir/javacpp/lib/"]

tasks.getByName('preBuild').dependsOn javacppExtract

} // api 'org.bytedeco:javacv-platform:1.5.10-SNAPSHOT' implementation group: 'org.bytedeco', name: 'javacv', version: "1.5.9" // javacpp group: 'org.bytedeco', name: 'openblas-platform', version: "5.1.2-1.5.8" javacpp group: 'org.bytedeco', name: 'opencv-platform', version: "4.7.0-1.5.9" javacpp group: 'org.bytedeco', name: 'ffmpeg-platform', version: "6.0-1.5.9"

implementation 'com.guaishou.bzlib:bzyuv:1.1.19@aar'

// api "org.bytedeco:javacv-platform:1.5.9"

Logs : I/SUPPORT_ENCODER_TELEPHONE: avCodec != null, h264_mediacodec/ H.264 Android MediaCodec encoder I/OMXClient: IOmx service obtained I/ExtendedACodec: setupVideoEncoder() W/OMXUtils: do not know color format 0x7fa30c04 = 2141391876 W/OMXUtils: do not know color format 0x7fa30c00 = 2141391872 W/OMXUtils: do not know color format 0x7f000789 = 2130708361 E/ACodec: [OMX.qcom.video.encoder.avc] does not support color format 19 E/ExtendedACodec: [OMX.qcom.video.encoder.avc] configureCodec returning error -61 E/ACodec: signalError(omxError 0x80001001, internalError -61) E/ACodec: [OMX.qcom.video.encoder.avc] configureCodec returning error -61 E/ACodec: signalError(omxError 0x80001001, internalError -61) E/MediaCodec: Codec reported err 0xffffffc3, actionCode 0, while in state 3 E/MediaCodec: Codec reported err 0xffffffc3, actionCode 0, while in state 0 E/MediaCodec: configure failed with err 0xffffffc3, resetting... I/OMXClient: IOmx service obtained W/System.err: org.bytedeco.javacv.FFmpegFrameRecorder$Exception: avcodec_open2() error -542398533: Could not open video codec. (For more details, make sure FFmpegLogCallback.set() has been called.) W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.startUnsafe(FFmpegFrameRecorder.java:791) W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:437)

Any help will be appreciated

コントリビューターガイド