Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -22575,6 +22575,7 @@ package android.media { method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>); method public void queueSecureInputBuffer(int, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueSecureInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>); method public void release(); method public void releaseOutputBuffer(int, boolean); method public void releaseOutputBuffer(int, long); media/java/android/media/MediaCodec.java +50 −0 Original line number Diff line number Diff line Loading @@ -3210,6 +3210,51 @@ final public class MediaCodec { } } /** * Similar to {@link #queueInputBuffers queueInputBuffers} but submits multiple access units * in a buffer that is potentially encrypted. * <strong>Check out further notes at {@link #queueInputBuffers queueInputBuffers}.</strong> * * @param index The index of a client-owned input buffer previously returned * in a call to {@link #dequeueInputBuffer}. * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the * contents in the buffer. The ArrayDeque and the BufferInfo objects provided * can be recycled by the caller for re-use. * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} objects to facilitate the * decryption of the contents. The ArrayDeque and the CryptoInfo objects * provided can be reused immediately after the call returns. These objects * should correspond to bufferInfo objects to ensure correct decryption. * @throws IllegalStateException if not in the Executing state or not in asynchronous mode. * @throws MediaCodec.CodecException upon codec error. * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the * access units are not contiguous. * @throws CryptoException if an error occurs while attempting to decrypt the buffer. * An error code associated with the exception helps identify the * reason for the failure. */ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) public final void queueSecureInputBuffers( int index, @NonNull ArrayDeque<BufferInfo> bufferInfos, @NonNull ArrayDeque<CryptoInfo> cryptoInfos) { synchronized(mBufferLock) { if (mBufferMode == BUFFER_MODE_BLOCK) { throw new IncompatibleWithBlockModelException("queueSecureInputBuffers() " + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. " + "Please use getQueueRequest() to queue buffers"); } invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */); mDequeuedInputBuffers.remove(index); } try { native_queueSecureInputBuffers( index, bufferInfos.toArray(), cryptoInfos.toArray()); } catch (CryptoException | IllegalStateException | IllegalArgumentException e) { revalidateByteBuffer(mCachedInputBuffers, index, true /* input */); throw e; } } private native final void native_queueSecureInputBuffer( int index, int offset, Loading @@ -3217,6 +3262,11 @@ final public class MediaCodec { long presentationTimeUs, int flags) throws CryptoException; private native final void native_queueSecureInputBuffers( int index, @NonNull Object[] bufferInfos, @NonNull Object[] cryptoInfos) throws CryptoException, CodecException; /** * Returns the index of an input buffer to be filled with valid data * or -1 if no such buffer is currently available. Loading media/jni/android_media_MediaCodec.cpp +171 −2 Original line number Diff line number Diff line Loading @@ -458,6 +458,24 @@ status_t JMediaCodec::queueSecureInputBuffer( presentationTimeUs, flags, errorDetailMsg); } status_t JMediaCodec::queueSecureInputBuffers( size_t index, size_t offset, size_t size, const sp<RefBase> &auInfos_, const sp<RefBase> &cryptoInfos_, AString *errorDetailMsg) { sp<BufferInfosWrapper> auInfos((BufferInfosWrapper *)auInfos_.get()); sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get()); return mCodec->queueSecureInputBuffers( index, offset, size, auInfos, cryptoInfos, errorDetailMsg); } status_t JMediaCodec::queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, AString *errorDetailMsg) { Loading Loading @@ -2262,6 +2280,61 @@ struct NativeCryptoInfo { CryptoPlugin::Pattern mPattern; }; // This class takes away all dependencies on java(env and jni) and // could be used for taking cryptoInfo objects to MediaCodec. struct MediaCodecCryptoInfo: public CodecCryptoInfo { explicit MediaCodecCryptoInfo(const NativeCryptoInfo &cryptoInfo) { if (cryptoInfo.mErr == OK) { mNumSubSamples = cryptoInfo.mNumSubSamples; mMode = cryptoInfo.mMode; mPattern = cryptoInfo.mPattern; if (cryptoInfo.mKey != nullptr) { mKeyBuffer = ABuffer::CreateAsCopy(cryptoInfo.mKey, 16); mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr); } if (cryptoInfo.mIv != nullptr) { mIvBuffer = ABuffer::CreateAsCopy(cryptoInfo.mIv, 16); mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr); } if (cryptoInfo.mSubSamples != nullptr) { mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples); if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); for (int s = 0 ; s < mNumSubSamples ; s++) { samples[s].mNumBytesOfClearData = cryptoInfo.mSubSamples[s].mNumBytesOfClearData; samples[s].mNumBytesOfEncryptedData = cryptoInfo.mSubSamples[s].mNumBytesOfEncryptedData; } mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } } } explicit MediaCodecCryptoInfo(jint size) { mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * 1); mNumSubSamples = 1; if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); samples[0].mNumBytesOfClearData = size; samples[0].mNumBytesOfEncryptedData = 0; mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } ~MediaCodecCryptoInfo() {} protected: // all backup buffers for the base object. sp<ABuffer> mKeyBuffer; sp<ABuffer> mIvBuffer; sp<ABuffer> mSubSamplesBuffer; }; static void android_media_MediaCodec_queueSecureInputBuffer( JNIEnv *env, jobject thiz, Loading Loading @@ -2430,6 +2503,99 @@ static void android_media_MediaCodec_queueSecureInputBuffer( codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } static status_t extractCryptoInfosFromObjectArray(JNIEnv * const env, jint * const totalSize, std::vector<std::unique_ptr<CodecCryptoInfo>> * const cryptoInfoObjs, const jobjectArray &objArray, AString * const errorDetailMsg) { if (env == nullptr || cryptoInfoObjs == nullptr || totalSize == nullptr) { if (errorDetailMsg) { *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; } return BAD_VALUE; } const jsize numEntries = env->GetArrayLength(objArray); if (numEntries <= 0) { if (errorDetailMsg) { *errorDetailMsg = "Error: No CryptoInfo found while queuing for large frame input"; } return BAD_VALUE; } cryptoInfoObjs->clear(); *totalSize = 0; jint size = 0; for (jsize i = 0; i < numEntries ; i++) { jobject param = env->GetObjectArrayElement(objArray, i); if (param == NULL) { if (errorDetailMsg) { *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; } return BAD_VALUE; } NativeCryptoInfo nativeInfo(env, param); std::unique_ptr<CodecCryptoInfo> info(new MediaCodecCryptoInfo(nativeInfo)); for (int i = 0; i < info->mNumSubSamples; i++) { size += info->mSubSamples[i].mNumBytesOfClearData; size += info->mSubSamples[i].mNumBytesOfEncryptedData; } cryptoInfoObjs->push_back(std::move(info)); } *totalSize = size; return OK; } static void android_media_MediaCodec_queueSecureInputBuffers( JNIEnv *env, jobject thiz, jint index, jobjectArray bufferInfosObjs, jobjectArray cryptoInfoObjs) { ALOGV("android_media_MediaCodec_queueSecureInputBuffers"); sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } sp<BufferInfosWrapper> auInfos = new BufferInfosWrapper{decltype(auInfos->value)()}; sp<CryptoInfosWrapper> cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()}; AString errorDetailMsg; jint initialOffset = 0; jint totalSize = 0; status_t err = extractInfosFromObject( env, &initialOffset, &totalSize, &auInfos->value, bufferInfosObjs, &errorDetailMsg); if (err == OK) { err = extractCryptoInfosFromObjectArray(env, &totalSize, &cryptoInfos->value, cryptoInfoObjs, &errorDetailMsg); } if (err == OK) { err = codec->queueSecureInputBuffers( index, initialOffset, totalSize, auInfos, cryptoInfos, &errorDetailMsg); } throwExceptionAsNecessary( env, err, ACTION_CODE_FATAL, codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) { ALOGV("android_media_MediaCodec_mapHardwareBuffer"); AHardwareBuffer *hardwareBuffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer( Loading Loading @@ -2780,8 +2946,8 @@ static void android_media_MediaCodec_native_queueLinearBlock( "error occurred while converting tunings from Java to native"); return; } jint totalSize; jint initialOffset; jint totalSize = 0; jint initialOffset = 0; std::vector<AccessUnitInfo> infoVec; AString errorDetailMsg; err = extractInfosFromObject(env, Loading Loading @@ -3950,6 +4116,9 @@ static const JNINativeMethod gMethods[] = { { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", (void *)android_media_MediaCodec_queueSecureInputBuffer }, { "native_queueSecureInputBuffers", "(I[Ljava/lang/Object;[Ljava/lang/Object;)V", (void *)android_media_MediaCodec_queueSecureInputBuffers }, { "native_mapHardwareBuffer", "(Landroid/hardware/HardwareBuffer;)Landroid/media/Image;", (void *)android_media_MediaCodec_mapHardwareBuffer }, Loading media/jni/android_media_MediaCodec.h +8 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,14 @@ struct JMediaCodec : public AHandler { uint32_t flags, AString *errorDetailMsg); status_t queueSecureInputBuffers( size_t index, size_t offset, size_t size, const sp<RefBase> &auInfos, const sp<RefBase> &cryptoInfos, AString *errorDetailMsg); status_t queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -22575,6 +22575,7 @@ package android.media { method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>); method public void queueSecureInputBuffer(int, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueSecureInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>); method public void release(); method public void releaseOutputBuffer(int, boolean); method public void releaseOutputBuffer(int, long);
media/java/android/media/MediaCodec.java +50 −0 Original line number Diff line number Diff line Loading @@ -3210,6 +3210,51 @@ final public class MediaCodec { } } /** * Similar to {@link #queueInputBuffers queueInputBuffers} but submits multiple access units * in a buffer that is potentially encrypted. * <strong>Check out further notes at {@link #queueInputBuffers queueInputBuffers}.</strong> * * @param index The index of a client-owned input buffer previously returned * in a call to {@link #dequeueInputBuffer}. * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the * contents in the buffer. The ArrayDeque and the BufferInfo objects provided * can be recycled by the caller for re-use. * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} objects to facilitate the * decryption of the contents. The ArrayDeque and the CryptoInfo objects * provided can be reused immediately after the call returns. These objects * should correspond to bufferInfo objects to ensure correct decryption. * @throws IllegalStateException if not in the Executing state or not in asynchronous mode. * @throws MediaCodec.CodecException upon codec error. * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the * access units are not contiguous. * @throws CryptoException if an error occurs while attempting to decrypt the buffer. * An error code associated with the exception helps identify the * reason for the failure. */ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) public final void queueSecureInputBuffers( int index, @NonNull ArrayDeque<BufferInfo> bufferInfos, @NonNull ArrayDeque<CryptoInfo> cryptoInfos) { synchronized(mBufferLock) { if (mBufferMode == BUFFER_MODE_BLOCK) { throw new IncompatibleWithBlockModelException("queueSecureInputBuffers() " + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. " + "Please use getQueueRequest() to queue buffers"); } invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */); mDequeuedInputBuffers.remove(index); } try { native_queueSecureInputBuffers( index, bufferInfos.toArray(), cryptoInfos.toArray()); } catch (CryptoException | IllegalStateException | IllegalArgumentException e) { revalidateByteBuffer(mCachedInputBuffers, index, true /* input */); throw e; } } private native final void native_queueSecureInputBuffer( int index, int offset, Loading @@ -3217,6 +3262,11 @@ final public class MediaCodec { long presentationTimeUs, int flags) throws CryptoException; private native final void native_queueSecureInputBuffers( int index, @NonNull Object[] bufferInfos, @NonNull Object[] cryptoInfos) throws CryptoException, CodecException; /** * Returns the index of an input buffer to be filled with valid data * or -1 if no such buffer is currently available. Loading
media/jni/android_media_MediaCodec.cpp +171 −2 Original line number Diff line number Diff line Loading @@ -458,6 +458,24 @@ status_t JMediaCodec::queueSecureInputBuffer( presentationTimeUs, flags, errorDetailMsg); } status_t JMediaCodec::queueSecureInputBuffers( size_t index, size_t offset, size_t size, const sp<RefBase> &auInfos_, const sp<RefBase> &cryptoInfos_, AString *errorDetailMsg) { sp<BufferInfosWrapper> auInfos((BufferInfosWrapper *)auInfos_.get()); sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get()); return mCodec->queueSecureInputBuffers( index, offset, size, auInfos, cryptoInfos, errorDetailMsg); } status_t JMediaCodec::queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, AString *errorDetailMsg) { Loading Loading @@ -2262,6 +2280,61 @@ struct NativeCryptoInfo { CryptoPlugin::Pattern mPattern; }; // This class takes away all dependencies on java(env and jni) and // could be used for taking cryptoInfo objects to MediaCodec. struct MediaCodecCryptoInfo: public CodecCryptoInfo { explicit MediaCodecCryptoInfo(const NativeCryptoInfo &cryptoInfo) { if (cryptoInfo.mErr == OK) { mNumSubSamples = cryptoInfo.mNumSubSamples; mMode = cryptoInfo.mMode; mPattern = cryptoInfo.mPattern; if (cryptoInfo.mKey != nullptr) { mKeyBuffer = ABuffer::CreateAsCopy(cryptoInfo.mKey, 16); mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr); } if (cryptoInfo.mIv != nullptr) { mIvBuffer = ABuffer::CreateAsCopy(cryptoInfo.mIv, 16); mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr); } if (cryptoInfo.mSubSamples != nullptr) { mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples); if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); for (int s = 0 ; s < mNumSubSamples ; s++) { samples[s].mNumBytesOfClearData = cryptoInfo.mSubSamples[s].mNumBytesOfClearData; samples[s].mNumBytesOfEncryptedData = cryptoInfo.mSubSamples[s].mNumBytesOfEncryptedData; } mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } } } explicit MediaCodecCryptoInfo(jint size) { mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * 1); mNumSubSamples = 1; if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); samples[0].mNumBytesOfClearData = size; samples[0].mNumBytesOfEncryptedData = 0; mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } ~MediaCodecCryptoInfo() {} protected: // all backup buffers for the base object. sp<ABuffer> mKeyBuffer; sp<ABuffer> mIvBuffer; sp<ABuffer> mSubSamplesBuffer; }; static void android_media_MediaCodec_queueSecureInputBuffer( JNIEnv *env, jobject thiz, Loading Loading @@ -2430,6 +2503,99 @@ static void android_media_MediaCodec_queueSecureInputBuffer( codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } static status_t extractCryptoInfosFromObjectArray(JNIEnv * const env, jint * const totalSize, std::vector<std::unique_ptr<CodecCryptoInfo>> * const cryptoInfoObjs, const jobjectArray &objArray, AString * const errorDetailMsg) { if (env == nullptr || cryptoInfoObjs == nullptr || totalSize == nullptr) { if (errorDetailMsg) { *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; } return BAD_VALUE; } const jsize numEntries = env->GetArrayLength(objArray); if (numEntries <= 0) { if (errorDetailMsg) { *errorDetailMsg = "Error: No CryptoInfo found while queuing for large frame input"; } return BAD_VALUE; } cryptoInfoObjs->clear(); *totalSize = 0; jint size = 0; for (jsize i = 0; i < numEntries ; i++) { jobject param = env->GetObjectArrayElement(objArray, i); if (param == NULL) { if (errorDetailMsg) { *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; } return BAD_VALUE; } NativeCryptoInfo nativeInfo(env, param); std::unique_ptr<CodecCryptoInfo> info(new MediaCodecCryptoInfo(nativeInfo)); for (int i = 0; i < info->mNumSubSamples; i++) { size += info->mSubSamples[i].mNumBytesOfClearData; size += info->mSubSamples[i].mNumBytesOfEncryptedData; } cryptoInfoObjs->push_back(std::move(info)); } *totalSize = size; return OK; } static void android_media_MediaCodec_queueSecureInputBuffers( JNIEnv *env, jobject thiz, jint index, jobjectArray bufferInfosObjs, jobjectArray cryptoInfoObjs) { ALOGV("android_media_MediaCodec_queueSecureInputBuffers"); sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } sp<BufferInfosWrapper> auInfos = new BufferInfosWrapper{decltype(auInfos->value)()}; sp<CryptoInfosWrapper> cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()}; AString errorDetailMsg; jint initialOffset = 0; jint totalSize = 0; status_t err = extractInfosFromObject( env, &initialOffset, &totalSize, &auInfos->value, bufferInfosObjs, &errorDetailMsg); if (err == OK) { err = extractCryptoInfosFromObjectArray(env, &totalSize, &cryptoInfos->value, cryptoInfoObjs, &errorDetailMsg); } if (err == OK) { err = codec->queueSecureInputBuffers( index, initialOffset, totalSize, auInfos, cryptoInfos, &errorDetailMsg); } throwExceptionAsNecessary( env, err, ACTION_CODE_FATAL, codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) { ALOGV("android_media_MediaCodec_mapHardwareBuffer"); AHardwareBuffer *hardwareBuffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer( Loading Loading @@ -2780,8 +2946,8 @@ static void android_media_MediaCodec_native_queueLinearBlock( "error occurred while converting tunings from Java to native"); return; } jint totalSize; jint initialOffset; jint totalSize = 0; jint initialOffset = 0; std::vector<AccessUnitInfo> infoVec; AString errorDetailMsg; err = extractInfosFromObject(env, Loading Loading @@ -3950,6 +4116,9 @@ static const JNINativeMethod gMethods[] = { { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", (void *)android_media_MediaCodec_queueSecureInputBuffer }, { "native_queueSecureInputBuffers", "(I[Ljava/lang/Object;[Ljava/lang/Object;)V", (void *)android_media_MediaCodec_queueSecureInputBuffers }, { "native_mapHardwareBuffer", "(Landroid/hardware/HardwareBuffer;)Landroid/media/Image;", (void *)android_media_MediaCodec_mapHardwareBuffer }, Loading
media/jni/android_media_MediaCodec.h +8 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,14 @@ struct JMediaCodec : public AHandler { uint32_t flags, AString *errorDetailMsg); status_t queueSecureInputBuffers( size_t index, size_t offset, size_t size, const sp<RefBase> &auInfos, const sp<RefBase> &cryptoInfos, AString *errorDetailMsg); status_t queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, Loading