public class

BufferCopiedEncodedData

extends java.lang.Object

implements EncodedData

 java.lang.Object

↳androidx.camera.video.internal.encoder.BufferCopiedEncodedData

Gradle dependencies

compile group: 'androidx.camera', name: 'camera-video', version: '1.2.0-alpha01'

  • groupId: androidx.camera
  • artifactId: camera-video
  • version: 1.2.0-alpha01

Artifact androidx.camera:camera-video:1.2.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

A class used to hold a copy of encoded data to prevent occupying the byte buffer of the media codec.

To reduce the memory used, the capacity of the copied byte buffer may not equal to its source, only the required size is allocated to put the copied data.

Summary

Constructors
publicBufferCopiedEncodedData(EncodedData encodedData)

Methods
public voidclose()

No need to call this function.

public MediaCodec.BufferInfogetBufferInfo()

public java.nio.ByteBuffergetByteBuffer()

public <any>getClosedFuture()

No need to call this function.

public longgetPresentationTimeUs()

public booleanisKeyFrame()

public longsize()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public BufferCopiedEncodedData(EncodedData encodedData)

Methods

public java.nio.ByteBuffer getByteBuffer()

public MediaCodec.BufferInfo getBufferInfo()

public long getPresentationTimeUs()

public long size()

public boolean isKeyFrame()

public void close()

No need to call this function. Resources will be released by garbage collection.

public <any> getClosedFuture()

No need to call this function. Resources will be released by garbage collection.

Source

/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.camera.video.internal.encoder;

import android.media.MediaCodec;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.core.impl.utils.futures.Futures;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.core.util.Preconditions;

import com.google.common.util.concurrent.ListenableFuture;

import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicReference;

/**
 * A class used to hold a copy of encoded data to prevent occupying the byte buffer of the media
 * codec.
 *
 * <p> To reduce the memory used, the capacity of the copied byte buffer may not equal to its
 * source, only the required size is allocated to put the copied data.
 */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
public class BufferCopiedEncodedData implements EncodedData {

    private final ByteBuffer mByteBuffer;
    private final MediaCodec.BufferInfo mBufferInfo;
    private final ListenableFuture<Void> mClosedFuture;
    private final CallbackToFutureAdapter.Completer<Void> mClosedCompleter;

    public BufferCopiedEncodedData(@NonNull EncodedData encodedData) {
        mBufferInfo = generateCopiedByteInfo(encodedData);
        mByteBuffer = generateCopiedByteBuffer(encodedData);

        // Prepare close future and completer
        AtomicReference<CallbackToFutureAdapter.Completer<Void>> ref = new AtomicReference<>();
        mClosedFuture = CallbackToFutureAdapter.getFuture(completer -> {
            ref.set(completer);
            return "Data closed";
        });
        mClosedCompleter = Preconditions.checkNotNull(ref.get());
    }

    @NonNull
    private MediaCodec.BufferInfo generateCopiedByteInfo(@NonNull EncodedData encodedData) {
        MediaCodec.BufferInfo bufferInfo = encodedData.getBufferInfo();

        MediaCodec.BufferInfo copiedBufferInfo = new MediaCodec.BufferInfo();
        copiedBufferInfo.set(
                0,
                bufferInfo.size,
                bufferInfo.presentationTimeUs,
                bufferInfo.flags
        );

        return copiedBufferInfo;
    }

    @NonNull
    private ByteBuffer generateCopiedByteBuffer(@NonNull EncodedData encodedData) {
        ByteBuffer byteBuffer = encodedData.getByteBuffer();
        MediaCodec.BufferInfo bufferInfo = encodedData.getBufferInfo();
        byteBuffer.position(bufferInfo.offset);
        byteBuffer.limit(bufferInfo.offset + bufferInfo.size);

        // Copy only the part that contents data
        ByteBuffer copiedByteBuffer = ByteBuffer.allocate(bufferInfo.size);
        copiedByteBuffer.put(byteBuffer);

        return copiedByteBuffer;
    }

    /** {@inheritDoc} */
    @NonNull
    @Override
    public ByteBuffer getByteBuffer() {
        return mByteBuffer;
    }

    /** {@inheritDoc} */
    @NonNull
    @Override
    public MediaCodec.BufferInfo getBufferInfo() {
        return mBufferInfo;
    }

    /** {@inheritDoc} */
    @Override
    public long getPresentationTimeUs() {
        return mBufferInfo.presentationTimeUs;
    }

    /** {@inheritDoc} */
    @Override
    public long size() {
        return mBufferInfo.size;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isKeyFrame() {
        return (mBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0;
    }

    /**
     * No need to call this function. Resources will be released by garbage collection.
     */
    @Override
    public void close() {
        mClosedCompleter.set(null);
    }

    /**
     * No need to call this function. Resources will be released by garbage collection.
     */
    @NonNull
    @Override
    public ListenableFuture<Void> getClosedFuture() {
        return Futures.nonCancellationPropagating(mClosedFuture);
    }
}