bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.57k stars 1.58k forks source link

how to use hw accelerator with FFMpegFrameRecorder #2046

Open 1goresha opened 1 year ago

1goresha commented 1 year ago

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

saudet commented 1 year ago

@tmm1 Any ideas?

1goresha commented 1 year ago

I added FFmpegLogCallback.set()

Logs : I/OMXClient: IOmx service obtained W/System.err: Info: [h264_mediacodec @ 0xb4000078e7293800] Use 30 as the default MediaFormat frame-rate 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: Error: [amediacodec @ 0xb400007941838200] android.media.MediaCodec$CodecException: Error 0xffffffc3 W/System.err: Error: [h264_mediacodec @ 0xb4000078e7293800] MediaCodec configure failed, Generic error in an external library I/BpBinder: onLastStrongRef automatically unlinking death recipients: android.media.IResourceManagerService 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)

absir commented 1 year ago

redroid have same error

saudet commented 1 year ago

Trying the "solutions" here might fix this error: https://copyprogramming.com/howto/avcodec-open2-error-542398533-generic-error-in-an-external-library

saudet commented 10 months ago

Please try again with the snapshots: http://bytedeco.org/builds/

iChengc commented 9 months ago

I got the same error by using FFMPEGFrameGrabber to grab frames from a rtsp live stream with the 1.5.11-SNAPSHOT version. Has any ideas?

Info: Input #0, rtsp, from 'rtsp://10.0.3.16:8080/h264_ulaw.sdp': Info: Metadata: Info: title : Info: IP Webcam Info: Info: Duration: Info: N/A Info: , bitrate: Info: N/A Info: Info: Stream #0:0 Debug: , 0, 1/90000 Info: : Video: h264, 1 reference frame, none, 480x640 (0x0), 0/1 Info: , Info: 90k tbn Info: Info: Stream #0:1 Debug: , 0, 1/8000 Info: : Audio: pcm_mulaw, 8000 Hz, mono, 64 kb/s Info: Debug: [h264_mp4toannexb @ 0xb400007af67f60f0] The input looks like it is Annex B already Debug: [h264_mediacodec @ 0xb400007ba6827c30] nal_unit_type: 7(SPS), nal_ref_idc: 3 Debug: [h264_mediacodec @ 0xb400007ba6827c30] nal_unit_type: 8(PPS), nal_ref_idc: 3 Debug: [h264_mediacodec @ 0xb400007ba6827c30] Decoding VUI Error: [h264_mediacodec @ 0xb400007ba6827c30] MediaCodec 0x0 failed to start org.bytedeco.javacv.FFmpegFrameGrabber$Exception: avcodec_open2() error -542398533: Could not open video codec. (For more details, make sure FFmpegLogCallback.set() has been called.) W at org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe(FFmpegFrameGrabber.java:1065)