| Index: media/base/android/media_codec_bridge_impl.cc
|
| diff --git a/media/base/android/sdk_media_codec_bridge.cc b/media/base/android/media_codec_bridge_impl.cc
|
| similarity index 86%
|
| rename from media/base/android/sdk_media_codec_bridge.cc
|
| rename to media/base/android/media_codec_bridge_impl.cc
|
| index d80e7279c409b150051321ca421d1476546c818d..15a33a421961ca7d36121852d8a94e803390c34d 100644
|
| --- a/media/base/android/sdk_media_codec_bridge.cc
|
| +++ b/media/base/android/media_codec_bridge_impl.cc
|
| @@ -2,7 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "media/base/android/sdk_media_codec_bridge.h"
|
| +#include "media/base/android/media_codec_bridge_impl.h"
|
|
|
| #include <algorithm>
|
| #include <limits>
|
| @@ -36,6 +36,7 @@ using base::android::ScopedJavaLocalRef;
|
| } while (0)
|
|
|
| namespace media {
|
| +namespace {
|
|
|
| enum {
|
| kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME
|
| @@ -43,14 +44,7 @@ enum {
|
| kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE
|
| };
|
|
|
| -static ScopedJavaLocalRef<jintArray>
|
| -ToJavaIntArray(JNIEnv* env, std::unique_ptr<jint[]> native_array, int size) {
|
| - ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
|
| - env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
|
| - return j_array;
|
| -}
|
| -
|
| -static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
|
| +const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
|
| switch (codec) {
|
| case kCodecMP3:
|
| return "audio/mpeg";
|
| @@ -69,7 +63,7 @@ static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
|
| }
|
| }
|
|
|
| -static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
|
| +const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
|
| switch (codec) {
|
| case kCodecH264:
|
| return "video/avc";
|
| @@ -84,10 +78,19 @@ static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
|
| }
|
| }
|
|
|
| -SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime,
|
| - bool is_secure,
|
| - MediaCodecDirection direction,
|
| - bool require_software_codec) {
|
| +static ScopedJavaLocalRef<jintArray>
|
| +ToJavaIntArray(JNIEnv* env, std::unique_ptr<jint[]> native_array, int size) {
|
| + ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
|
| + env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
|
| + return j_array;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +MediaCodecBridgeImpl::MediaCodecBridgeImpl(const std::string& mime,
|
| + bool is_secure,
|
| + MediaCodecDirection direction,
|
| + bool require_software_codec) {
|
| JNIEnv* env = AttachCurrentThread();
|
| DCHECK(!mime.empty());
|
| ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
|
| @@ -95,29 +98,29 @@ SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime,
|
| env, j_mime, is_secure, direction, require_software_codec));
|
| }
|
|
|
| -SdkMediaCodecBridge::~SdkMediaCodecBridge() {
|
| +MediaCodecBridgeImpl::~MediaCodecBridgeImpl() {
|
| JNIEnv* env = AttachCurrentThread();
|
| if (j_media_codec_.obj())
|
| Java_MediaCodecBridge_release(env, j_media_codec_);
|
| }
|
|
|
| -bool SdkMediaCodecBridge::Start() {
|
| +bool MediaCodecBridgeImpl::Start() {
|
| JNIEnv* env = AttachCurrentThread();
|
| return Java_MediaCodecBridge_start(env, j_media_codec_);
|
| }
|
|
|
| -void SdkMediaCodecBridge::Stop() {
|
| +void MediaCodecBridgeImpl::Stop() {
|
| JNIEnv* env = AttachCurrentThread();
|
| Java_MediaCodecBridge_stop(env, j_media_codec_);
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::Flush() {
|
| +MediaCodecStatus MediaCodecBridgeImpl::Flush() {
|
| JNIEnv* env = AttachCurrentThread();
|
| return static_cast<MediaCodecStatus>(
|
| Java_MediaCodecBridge_flush(env, j_media_codec_));
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::GetOutputSize(gfx::Size* size) {
|
| +MediaCodecStatus MediaCodecBridgeImpl::GetOutputSize(gfx::Size* size) {
|
| JNIEnv* env = AttachCurrentThread();
|
| ScopedJavaLocalRef<jobject> result =
|
| Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_);
|
| @@ -130,7 +133,7 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputSize(gfx::Size* size) {
|
| return status;
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate(
|
| +MediaCodecStatus MediaCodecBridgeImpl::GetOutputSamplingRate(
|
| int* sampling_rate) {
|
| JNIEnv* env = AttachCurrentThread();
|
| ScopedJavaLocalRef<jobject> result =
|
| @@ -142,7 +145,7 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate(
|
| return status;
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount(
|
| +MediaCodecStatus MediaCodecBridgeImpl::GetOutputChannelCount(
|
| int* channel_count) {
|
| JNIEnv* env = AttachCurrentThread();
|
| ScopedJavaLocalRef<jobject> result =
|
| @@ -154,12 +157,12 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount(
|
| return status;
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
|
| +MediaCodecStatus MediaCodecBridgeImpl::QueueInputBuffer(
|
| int index,
|
| const uint8_t* data,
|
| size_t data_size,
|
| base::TimeDelta presentation_time) {
|
| - DVLOG(3) << __func__ << index << ": " << data_size;
|
| + DVLOG(3) << __func__ << " " << index << ": " << data_size;
|
| if (data_size >
|
| base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
|
| return MEDIA_CODEC_ERROR;
|
| @@ -172,19 +175,16 @@ MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
|
| presentation_time.InMicroseconds(), 0));
|
| }
|
|
|
| -// TODO(timav): Combine this and above methods together keeping only the first
|
| -// interface after we switch to Spitzer pipeline.
|
| -MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
|
| +MediaCodecStatus MediaCodecBridgeImpl::QueueSecureInputBuffer(
|
| int index,
|
| const uint8_t* data,
|
| size_t data_size,
|
| - const std::vector<char>& key_id,
|
| - const std::vector<char>& iv,
|
| - const SubsampleEntry* subsamples,
|
| - int subsamples_size,
|
| + const std::string& key_id,
|
| + const std::string& iv,
|
| + const std::vector<SubsampleEntry>& subsamples,
|
| const EncryptionScheme& encryption_scheme,
|
| base::TimeDelta presentation_time) {
|
| - DVLOG(3) << __func__ << index << ": " << data_size;
|
| + DVLOG(3) << __func__ << " " << index << ": " << data_size;
|
| if (data_size >
|
| base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
|
| return MEDIA_CODEC_ERROR;
|
| @@ -198,23 +198,20 @@ MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
|
| ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray(
|
| env, reinterpret_cast<const uint8_t*>(iv.data()), iv.size());
|
|
|
| - // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
|
| + // The MediaCodec.CryptoInfo documentation says to pass NULL for |clear_array|
|
| // to indicate that all data is encrypted. But it doesn't specify what
|
| - // |cypher_array| and |subsamples_size| should be in that case. Passing
|
| + // |cypher_array| and |subsamples_size| should be in that case. We pass
|
| // one subsample here just to be on the safe side.
|
| - int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
|
| + int num_subsamples = std::max(static_cast<size_t>(1), subsamples.size());
|
|
|
| - std::unique_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
|
| - std::unique_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
|
| + std::unique_ptr<jint[]> native_clear_array(new jint[num_subsamples]);
|
| + std::unique_ptr<jint[]> native_cypher_array(new jint[num_subsamples]);
|
|
|
| - if (subsamples_size == 0) {
|
| - DCHECK(!subsamples);
|
| + if (subsamples.empty()) {
|
| native_clear_array[0] = 0;
|
| native_cypher_array[0] = data_size;
|
| } else {
|
| - DCHECK_GT(subsamples_size, 0);
|
| - DCHECK(subsamples);
|
| - for (int i = 0; i < subsamples_size; ++i) {
|
| + for (size_t i = 0; i < subsamples.size(); ++i) {
|
| DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max());
|
| if (subsamples[i].cypher_bytes >
|
| static_cast<uint32_t>(std::numeric_limits<jint>::max())) {
|
| @@ -227,28 +224,28 @@ MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
|
| }
|
|
|
| ScopedJavaLocalRef<jintArray> clear_array =
|
| - ToJavaIntArray(env, std::move(native_clear_array), new_subsamples_size);
|
| + ToJavaIntArray(env, std::move(native_clear_array), num_subsamples);
|
| ScopedJavaLocalRef<jintArray> cypher_array =
|
| - ToJavaIntArray(env, std::move(native_cypher_array), new_subsamples_size);
|
| + ToJavaIntArray(env, std::move(native_cypher_array), num_subsamples);
|
|
|
| return static_cast<MediaCodecStatus>(
|
| Java_MediaCodecBridge_queueSecureInputBuffer(
|
| env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(),
|
| - clear_array, cypher_array, new_subsamples_size,
|
| + clear_array, cypher_array, num_subsamples,
|
| static_cast<int>(encryption_scheme.mode()),
|
| static_cast<int>(encryption_scheme.pattern().encrypt_blocks()),
|
| static_cast<int>(encryption_scheme.pattern().skip_blocks()),
|
| presentation_time.InMicroseconds()));
|
| }
|
|
|
| -void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
|
| +void MediaCodecBridgeImpl::QueueEOS(int input_buffer_index) {
|
| DVLOG(3) << __func__ << ": " << input_buffer_index;
|
| JNIEnv* env = AttachCurrentThread();
|
| Java_MediaCodecBridge_queueInputBuffer(
|
| env, j_media_codec_, input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream);
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer(
|
| +MediaCodecStatus MediaCodecBridgeImpl::DequeueInputBuffer(
|
| base::TimeDelta timeout,
|
| int* index) {
|
| JNIEnv* env = AttachCurrentThread();
|
| @@ -261,7 +258,7 @@ MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer(
|
| return status;
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer(
|
| +MediaCodecStatus MediaCodecBridgeImpl::DequeueOutputBuffer(
|
| base::TimeDelta timeout,
|
| int* index,
|
| size_t* offset,
|
| @@ -295,15 +292,15 @@ MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer(
|
| return status;
|
| }
|
|
|
| -void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
|
| +void MediaCodecBridgeImpl::ReleaseOutputBuffer(int index, bool render) {
|
| DVLOG(3) << __func__ << ": " << index;
|
| JNIEnv* env = AttachCurrentThread();
|
| Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_, index, render);
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
|
| - uint8_t** data,
|
| - size_t* capacity) {
|
| +MediaCodecStatus MediaCodecBridgeImpl::GetInputBuffer(int input_buffer_index,
|
| + uint8_t** data,
|
| + size_t* capacity) {
|
| JNIEnv* env = AttachCurrentThread();
|
| ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
|
| env, j_media_codec_, input_buffer_index));
|
| @@ -316,7 +313,22 @@ MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
|
| return MEDIA_CODEC_OK;
|
| }
|
|
|
| -MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(
|
| +MediaCodecStatus MediaCodecBridgeImpl::CopyFromOutputBuffer(int index,
|
| + size_t offset,
|
| + void* dst,
|
| + size_t num) {
|
| + const uint8_t* src_data = nullptr;
|
| + size_t src_capacity = 0;
|
| + MediaCodecStatus status =
|
| + GetOutputBufferAddress(index, offset, &src_data, &src_capacity);
|
| + if (status == MEDIA_CODEC_OK) {
|
| + CHECK_GE(src_capacity, num);
|
| + memcpy(dst, src_data, num);
|
| + }
|
| + return status;
|
| +}
|
| +
|
| +MediaCodecStatus MediaCodecBridgeImpl::GetOutputBufferAddress(
|
| int index,
|
| size_t offset,
|
| const uint8_t** addr,
|
| @@ -335,7 +347,7 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(
|
| return MEDIA_CODEC_OK;
|
| }
|
|
|
| -std::string SdkMediaCodecBridge::GetName() {
|
| +std::string MediaCodecBridgeImpl::GetName() {
|
| if (base::android::BuildInfo::GetInstance()->sdk_int() < 18)
|
| return "";
|
| JNIEnv* env = AttachCurrentThread();
|
| @@ -344,6 +356,27 @@ std::string SdkMediaCodecBridge::GetName() {
|
| return ConvertJavaStringToUTF8(env, j_name);
|
| }
|
|
|
| +bool MediaCodecBridgeImpl::FillInputBuffer(int index,
|
| + const uint8_t* data,
|
| + size_t size) {
|
| + uint8_t* dst = nullptr;
|
| + size_t capacity = 0;
|
| + if (GetInputBuffer(index, &dst, &capacity) != MEDIA_CODEC_OK) {
|
| + LOG(ERROR) << "GetInputBuffer failed";
|
| + return false;
|
| + }
|
| + CHECK(dst);
|
| +
|
| + if (size > capacity) {
|
| + LOG(ERROR) << "Input buffer size " << size
|
| + << " exceeds MediaCodec input buffer capacity: " << capacity;
|
| + return false;
|
| + }
|
| +
|
| + memcpy(dst, data, size);
|
| + return true;
|
| +}
|
| +
|
| // static
|
| AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
|
| if (!MediaCodecUtil::IsMediaCodecAvailable())
|
| @@ -369,7 +402,7 @@ bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
|
| AudioCodecBridge::AudioCodecBridge(const std::string& mime)
|
| // Audio codec doesn't care about security level and there is no need for
|
| // audio encoding yet.
|
| - : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER, false) {}
|
| + : MediaCodecBridgeImpl(mime, false, MEDIA_CODEC_DECODER, false) {}
|
|
|
| bool AudioCodecBridge::ConfigureAndStart(const AudioDecoderConfig& config,
|
| jobject media_crypto) {
|
| @@ -657,7 +690,7 @@ VideoCodecBridge::VideoCodecBridge(const std::string& mime,
|
| bool is_secure,
|
| MediaCodecDirection direction,
|
| bool require_software_codec)
|
| - : SdkMediaCodecBridge(mime, is_secure, direction, require_software_codec),
|
| + : MediaCodecBridgeImpl(mime, is_secure, direction, require_software_codec),
|
| adaptive_playback_supported_for_testing_(-1) {}
|
|
|
| bool VideoCodecBridge::SetSurface(jobject surface) {
|
|
|