При использовании MediaCode c в режиме asyn c проблема в том, что я не получаю MediaCode c .BUFFER_FLAG_END_OF_STREAM - PullRequest
0 голосов
/ 16 июня 2020

Я создаю приложение для потоковой передачи. Я столкнулся с проблемой, вот код

Я хочу транслировать поток с камеры на сервер и надеюсь, что получу ByteBuffer в onOutputBufferAvailable (). Я получаю выходной буфер, но никогда не получаю MediaCodec.BUFFER_FLAG_END_OF_STREAM при вызове stopVideoCapture()

Вот сегменты кода

Создание медиа-кода c

 private val recorderStreamSurface by lazy {
    val format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, width, height)
    val frameRate = 30 // 30 fps
    var recorderStreamSurface: Surface? = null
    // Set some required properties. The media codec may fail if these aren't defined.
    format.setInteger(
        MediaFormat.KEY_COLOR_FORMAT,
        MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
    )
    format.setInteger(MediaFormat.KEY_BIT_RATE, 6000000) // 6Mbps
    format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
    format.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate)
    format.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1000000 / frameRate)
    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1)
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1) // 1 seconds between I-frames
    videoEncoder = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE)
    // Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into.
    try {

        videoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
        recorderStreamSurface = videoEncoder.createInputSurface()

         videoEncoder.setCallback(object : MediaCodec.Callback() {
             override fun onError(codec: MediaCodec, exception: MediaCodec.CodecException) {
                 Log.d(TAG, "==onError $codec $exception")
                 serverChannel.onError(exception)
             }

             override fun onOutputFormatChanged(codec: MediaCodec, format: MediaFormat) {
                 Log.d(TAG, "video encoder: output format changed")
             }

             override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
                 Log.d(TAG, "video encoder: returned input buffer: $index")
                 val frameData: ByteArray
                 frameData = queue.take().array()

                 val inputData = codec.getInputBuffer(index)
                 inputData!!.clear()
                 inputData.put(frameData)

                 codec.queueInputBuffer(index, 0, frameData.size, 0, 0)
             }

             override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, info: MediaCodec.BufferInfo) {
                 Log.d(TAG, "video encoder: returned output buffer: $index flag : ${info.flags}")
                 Log.d(TAG, "video encoder: returned buffer of size " + info.size)

                 if ((info.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                     Log.i(TAG,"serverChannel.onCompleted()1")
                 }

                 videoEncoder.releaseOutputBuffer(index, false)
             }
         })
        videoEncoder.start()
    } catch (e: IOException) {
        videoEncoder.stop()
        videoEncoder.release()
        serverChannel.onError(e)
    }
    recorderStreamSurface
}

локальные переменные

lateinit var videoEncoder: MediaCodec
val queue: ArrayBlockingQueue<ByteBuffer> = ArrayBlockingQueue<ByteBuffer>(10)
val targets by lazy { listOf(viewFinder.holder.surface, recorderStreamSurface!!) }
private const val VIDEO_MIME_TYPE = "video/avc"
val cameraId = "1"
val fps = 30
val width = 1080
val height = 1920

Запрос на запись

 private val recordRequest: CaptureRequest by lazy {
    // Capture request holds references to target surfaces
    session.device.createCaptureRequest(CameraDevice.TEMPLATE_RECORD).apply {
        // Add the preview and recording surface targets
        for (target: Surface in targets) {
            addTarget(target)
        }
        // Sets user requested FPS for all targets
        set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(fps, fps))
    }.build()
}

и, наконец, запуск и остановка записи

private fun startVideoCapture() {

    // Prevents screen rotation during the video recording
    requireActivity().requestedOrientation =
        ActivityInfo.SCREEN_ORIENTATION_LOCKED
    session.setRepeatingRequest(previewRequest, null, cameraHandler)
    // Start recording repeating requests, which will stop the ongoing preview
    //  repeating requests without having to explicitly call `session.stopRepeating`
    session.setRepeatingRequest(recordRequest, null, cameraHandler)

    recordingStartMillis = System.currentTimeMillis()
    Log.d(TAG, "Recording started")
}


private fun stopVideoCapture() {
    // Unlocks screen rotation after recording finished
    requireActivity().requestedOrientation =
        ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED

    videoEncoder.stop()
    videoEncoder.release()
    Log.d(TAG, "Recording stopped")
    session.setRepeatingRequest(previewRequest, null, cameraHandler)
}
...