summaryrefslogtreecommitdiffstats
path: root/media/base/android/media_codec_bridge.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/base/android/media_codec_bridge.cc')
-rw-r--r--media/base/android/media_codec_bridge.cc60
1 files changed, 57 insertions, 3 deletions
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc
index e466654..bd4c274 100644
--- a/media/base/android/media_codec_bridge.cc
+++ b/media/base/android/media_codec_bridge.cc
@@ -281,8 +281,9 @@ AudioCodecBridge::AudioCodecBridge(const AudioCodec codec)
: MediaCodecBridge(AudioCodecToMimeType(codec)) {
}
-void AudioCodecBridge::Start(
- const AudioCodec codec, int sample_rate, int channel_count) {
+bool AudioCodecBridge::Start(
+ const AudioCodec codec, int sample_rate, int channel_count,
+ const uint8* extra_data, size_t extra_data_size) {
JNIEnv* env = AttachCurrentThread();
DCHECK(AudioCodecToMimeType(codec));
@@ -292,16 +293,68 @@ void AudioCodecBridge::Start(
JNI_MediaFormat::Java_MediaFormat_createAudioFormat(
env, j_mime.obj(), sample_rate, channel_count));
DCHECK(!j_format.is_null());
+
+ if (extra_data_size > 0) {
+ DCHECK_EQ(kCodecVorbis, codec);
+ if (extra_data[0] != 2) {
+ LOG(ERROR) << "Invalid number of headers before the codec header: "
+ << extra_data[0];
+ return false;
+ }
+
+ size_t header_length[2];
+ // |total_length| keeps track of the total number of bytes before the last
+ // header.
+ size_t total_length = 1;
+ const uint8* current_pos = extra_data;
+ // Calculate the length of the first 2 headers.
+ for (int i = 0; i < 2; ++i) {
+ header_length[i] = 0;
+ while (total_length < extra_data_size) {
+ size_t size = *(++current_pos);
+ total_length += 1 + size;
+ if (total_length > 0x80000000) {
+ LOG(ERROR) << "Header size too large";
+ return false;
+ }
+ header_length[i] += size;
+ if (size < 0xFF)
+ break;
+ }
+ if (total_length >= extra_data_size) {
+ LOG(ERROR) << "Invalid header size in the extra data";
+ return false;
+ }
+ }
+ current_pos++;
+ // The first header is identification header.
+ jobject identification_header = env->NewDirectByteBuffer(
+ const_cast<uint8*>(current_pos), header_length[0]);
+ ScopedJavaLocalRef<jstring> j_csd_0 = ConvertUTF8ToJavaString(env, "csd-0");
+ JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
+ env, j_format.obj(), j_csd_0.obj(), identification_header);
+ // The last header is codec header.
+ jobject codec_header = env->NewDirectByteBuffer(
+ const_cast<uint8*>(extra_data + total_length),
+ extra_data_size - total_length);
+ ScopedJavaLocalRef<jstring> j_csd_1 = ConvertUTF8ToJavaString(env, "csd-1");
+ JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
+ env, j_format.obj(), j_csd_1.obj(), codec_header);
+ env->DeleteLocalRef(codec_header);
+ env->DeleteLocalRef(identification_header);
+ }
+
JNI_MediaCodec::Java_MediaCodec_configure(
env, media_codec(), j_format.obj(), NULL, NULL, 0);
StartInternal();
+ return true;
}
VideoCodecBridge::VideoCodecBridge(const VideoCodec codec)
: MediaCodecBridge(VideoCodecToMimeType(codec)) {
}
-void VideoCodecBridge::Start(
+bool VideoCodecBridge::Start(
const VideoCodec codec, const gfx::Size& size, jobject surface) {
JNIEnv* env = AttachCurrentThread();
DCHECK(VideoCodecToMimeType(codec));
@@ -315,6 +368,7 @@ void VideoCodecBridge::Start(
JNI_MediaCodec::Java_MediaCodec_configure(
env, media_codec(), j_format.obj(), surface, NULL, 0);
StartInternal();
+ return true;
}
} // namespace media