diff options
| author | 2020-04-24 18:44:45 +0000 | |
|---|---|---|
| committer | 2020-04-24 18:44:45 +0000 | |
| commit | 53897fd7d1523dfb200dcf446ffae4fdca066834 (patch) | |
| tree | 1f1992afa7ed67e5c79c396909744b40481fa5a9 | |
| parent | ed642064719edf033ca48cf026f563eb483526c0 (diff) | |
| parent | b8ebdb38cb8f5d140eef987139cd5f0ee02576db (diff) | |
Merge "media: fix MediaCodec operations using HardwareBuffer" into rvc-dev
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 12 | ||||
| -rw-r--r-- | media/jni/android_media_MediaCodec.cpp | 90 |
2 files changed, 67 insertions, 35 deletions
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 1d70a0dbc57c..d6496c0b3e02 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -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; diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 947cfc038b7f..b2b707b00829 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -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()); } |