Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48be1f43 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "media: fix MediaCodec operations using HardwareBuffer" into rvc-dev am:...

Merge "media: fix MediaCodec operations using HardwareBuffer" into rvc-dev am: 53897fd7 am: ee9de62c am: 3e059c03

Change-Id: Ibac39c975497903c3d7df1a0267ac6cdaf0f76e9
parents 40ef0fc0 3e059c03
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -4848,8 +4848,13 @@ final public class MediaCodec {
        }

        public MediaImage(
                @NonNull Image.Plane[] planes, int width, int height, int format, boolean readOnly,
                @NonNull ByteBuffer[] buffers, int[] rowStrides, int[] pixelStrides,
                int width, int height, int format, boolean readOnly,
                long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect, long context) {
            if (buffers.length != rowStrides.length || buffers.length != pixelStrides.length) {
                throw new IllegalArgumentException(
                        "buffers, rowStrides and pixelStrides should have the same length");
            }
            mWidth = width;
            mHeight = height;
            mFormat = format;
@@ -4858,7 +4863,10 @@ final public class MediaCodec {
            mIsReadOnly = readOnly;
            mBuffer = null;
            mInfo = null;
            mPlanes = planes;
            mPlanes = new MediaPlane[buffers.length];
            for (int i = 0; i < buffers.length; ++i) {
                mPlanes[i] = new MediaPlane(buffers[i], rowStrides[i], pixelStrides[i]);
            }

            // save offsets and info
            mXOffset = xOffset;
+57 −33
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <C2AllocatorGralloc.h>
#include <C2BlockInternal.h>
#include <C2Buffer.h>
#include <C2PlatformSupport.h>

#include <android/hardware/cas/native/1.0/IDescrambler.h>

@@ -1862,7 +1863,7 @@ static void android_media_MediaCodec_queueSecureInputBuffer(
            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
}

static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jobject bufferObj) {
static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) {
    ALOGV("android_media_MediaCodec_mapHardwareBuffer");
    AHardwareBuffer *hardwareBuffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer(
            env, bufferObj);
@@ -1878,9 +1879,9 @@ static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jobject b
    }
    bool readOnly = ((desc.usage & AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK) == 0);

    uint64_t cpuUsage = desc.usage;
    cpuUsage = (cpuUsage & AHARDWAREBUFFER_USAGE_CPU_READ_MASK);
    cpuUsage = (cpuUsage & AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK);
    uint64_t cpuUsage = 0;
    cpuUsage |= (desc.usage & AHARDWAREBUFFER_USAGE_CPU_READ_MASK);
    cpuUsage |= (desc.usage & AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK);

    AHardwareBuffer_Planes planes;
    int err = AHardwareBuffer_lockPlanes(
@@ -1895,42 +1896,56 @@ static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jobject b
        return nullptr;
    }

    ScopedLocalRef<jclass> planeClazz(
            env, env->FindClass("android/media/MediaCodec$MediaImage$MediaPlane"));
    ScopedLocalRef<jobjectArray> planeArray{
            env, env->NewObjectArray(3, planeClazz.get(), NULL)};
    CHECK(planeClazz.get() != NULL);
    jmethodID planeConstructID = env->GetMethodID(planeClazz.get(), "<init>",
            "([Ljava/nio/ByteBuffer;IIIII)V");
    ScopedLocalRef<jobjectArray> buffersArray{
            env, env->NewObjectArray(3, gByteBufferInfo.clazz, NULL)};
    ScopedLocalRef<jintArray> rowStridesArray{env, env->NewIntArray(3)};
    ScopedLocalRef<jintArray> pixelStridesArray{env, env->NewIntArray(3)};

    jboolean isCopy = JNI_FALSE;
    jint *rowStrides = env->GetIntArrayElements(rowStridesArray.get(), &isCopy);
    jint *pixelStrides = env->GetIntArrayElements(rowStridesArray.get(), &isCopy);

    // For Y plane
    int rowSampling = 1;
    int colSampling = 1;
    // plane indices are Y-U-V.
    for (uint32_t i = 0; i < 3; ++i) {
        const AHardwareBuffer_Plane &plane = planes.planes[i];
        int maxRowOffset = plane.rowStride * (desc.height / rowSampling - 1);
        int maxColOffset = plane.pixelStride * (desc.width / colSampling - 1);
        int maxOffset = maxRowOffset + maxColOffset;
        ScopedLocalRef<jobject> byteBuffer{env, CreateByteBuffer(
                env,
                plane.data,
                plane.rowStride * (desc.height - 1) + plane.pixelStride * (desc.width - 1) + 1,
                maxOffset + 1,
                0,
                plane.rowStride * (desc.height - 1) + plane.pixelStride * (desc.width - 1) + 1,
                maxOffset + 1,
                readOnly,
                true)};

        ScopedLocalRef<jobject> planeObj{env, env->NewObject(
                planeClazz.get(), planeConstructID,
                byteBuffer.get(), plane.rowStride, plane.pixelStride)};

        env->SetObjectArrayElement(planeArray.get(), i, planeObj.get());
        env->SetObjectArrayElement(buffersArray.get(), i, byteBuffer.get());
        rowStrides[i] = plane.rowStride;
        pixelStrides[i] = plane.pixelStride;
        // For U-V planes
        rowSampling = 2;
        colSampling = 2;
    }

    env->ReleaseIntArrayElements(rowStridesArray.get(), rowStrides, 0);
    env->ReleaseIntArrayElements(pixelStridesArray.get(), pixelStrides, 0);
    rowStrides = pixelStrides = nullptr;

    ScopedLocalRef<jclass> imageClazz(
            env, env->FindClass("android/media/MediaCodec$MediaImage"));
    CHECK(imageClazz.get() != NULL);

    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
            "([Landroid/media/Image$Plane;IIIZJIILandroid/graphics/Rect;J)V");
            "([Ljava/nio/ByteBuffer;[I[IIIIZJIILandroid/graphics/Rect;J)V");

    jobject img = env->NewObject(imageClazz.get(), imageConstructID,
            planeArray.get(),
            buffersArray.get(),
            rowStridesArray.get(),
            pixelStridesArray.get(),
            desc.width,
            desc.height,
            desc.format, // ???
@@ -1951,17 +1966,15 @@ static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jobject b
    return img;
}

static void android_media_MediaCodec_closeMediaImage(JNIEnv *, jlong context) {
static void android_media_MediaCodec_closeMediaImage(JNIEnv *, jclass, jlong context) {
    ALOGV("android_media_MediaCodec_closeMediaImage");
    if (context == 0) {
        return;
    }
    AHardwareBuffer *hardwareBuffer = (AHardwareBuffer *)context;

    int32_t fenceFd = -1;
    int err = AHardwareBuffer_unlock(hardwareBuffer, &fenceFd);
    if (err == 0) {
        sp<Fence> fence{new Fence(fenceFd)};
    } else {
    int err = AHardwareBuffer_unlock(hardwareBuffer, nullptr);
    if (err != 0) {
        ALOGI("closeMediaImage: failed to unlock (err=%d)", err);
        // Continue to release the hardwareBuffer
    }
@@ -2171,19 +2184,30 @@ static void android_media_MediaCodec_native_queueHardwareBuffer(
            env, bufferObj);
    sp<GraphicBuffer> graphicBuffer{AHardwareBuffer_to_GraphicBuffer(hardwareBuffer)};
    C2Handle *handle = WrapNativeCodec2GrallocHandle(
            graphicBuffer->handle, graphicBuffer->format,
            graphicBuffer->width, graphicBuffer->height,
            graphicBuffer->usage, graphicBuffer->stride);
    std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(handle);

    if (!block) {
            graphicBuffer->handle, graphicBuffer->width, graphicBuffer->height,
            graphicBuffer->format, graphicBuffer->usage, graphicBuffer->stride);
    static std::shared_ptr<C2Allocator> sGrallocAlloc = []() -> std::shared_ptr<C2Allocator> {
        std::shared_ptr<C2Allocator> alloc;
        c2_status_t err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
                C2PlatformAllocatorStore::GRALLOC, &alloc);
        if (err == C2_OK) {
            return alloc;
        }
        return nullptr;
    }();
    std::shared_ptr<C2GraphicAllocation> alloc;
    c2_status_t c2err = sGrallocAlloc->priorGraphicAllocation(handle, &alloc);
    if (c2err != C2_OK) {
        ALOGW("Failed to wrap AHardwareBuffer into C2GraphicAllocation");
        throwExceptionAsNecessary(env, BAD_VALUE);
        return;
    }
    std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
    std::shared_ptr<C2Buffer> buffer = C2Buffer::CreateGraphicBuffer(block->share(
            block->crop(), C2Fence{}));
    AString errorDetailMsg;
    err = codec->queueBuffer(index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
    err = codec->queueBuffer(
            index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str());
}