Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: media/base/android/webaudio_media_codec_bridge.cc

Issue 1565623002: Replace WebAudio MediaCodec usage with FFmpeg. A ~4x improvement. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Delete expectations. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/base/android/webaudio_media_codec_bridge.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <vector>
15
16 #include "base/android/context_utils.h"
17 #include "base/android/jni_android.h"
18 #include "base/android/jni_array.h"
19 #include "base/android/jni_string.h"
20 #include "base/files/scoped_file.h"
21 #include "base/logging.h"
22 #include "base/posix/eintr_wrapper.h"
23 #include "jni/WebAudioMediaCodecBridge_jni.h"
24 #include "media/base/android/webaudio_media_codec_info.h"
25
26 using base::android::AttachCurrentThread;
27
28 namespace media {
29
30 void WebAudioMediaCodecBridge::RunWebAudioMediaCodec(
31 base::SharedMemoryHandle encoded_audio_handle,
32 base::FileDescriptor pcm_output,
33 uint32_t data_size,
34 base::Closure on_decode_finished_cb) {
35 WebAudioMediaCodecBridge bridge(
36 encoded_audio_handle, pcm_output, data_size);
37
38 bridge.DecodeInMemoryAudioFile();
39 on_decode_finished_cb.Run();
40 }
41
42 WebAudioMediaCodecBridge::WebAudioMediaCodecBridge(
43 base::SharedMemoryHandle encoded_audio_handle,
44 base::FileDescriptor pcm_output,
45 uint32_t data_size)
46 : encoded_audio_handle_(encoded_audio_handle),
47 pcm_output_(pcm_output.fd),
48 data_size_(data_size) {
49 DVLOG(1) << "WebAudioMediaCodecBridge start **********************"
50 << " output fd = " << pcm_output.fd;
51 }
52
53 WebAudioMediaCodecBridge::~WebAudioMediaCodecBridge() {
54 if (close(pcm_output_)) {
55 DVLOG(1) << "Couldn't close output fd " << pcm_output_
56 << ": " << strerror(errno);
57 }
58 }
59
60 int WebAudioMediaCodecBridge::SaveEncodedAudioToFile(
61 JNIEnv* env,
62 jobject context) {
63 // Create a temporary file where we can save the encoded audio data.
64 std::string temporaryFile =
65 base::android::ConvertJavaStringToUTF8(
66 env,
67 Java_WebAudioMediaCodecBridge_createTempFile(env, context).obj());
68
69 // Open the file and unlink it, so that it will be actually removed
70 // when we close the file.
71 base::ScopedFD fd(open(temporaryFile.c_str(), O_RDWR));
72 if (unlink(temporaryFile.c_str())) {
73 VLOG(0) << "Couldn't unlink temp file " << temporaryFile
74 << ": " << strerror(errno);
75 }
76
77 if (!fd.is_valid()) {
78 return -1;
79 }
80
81 // Create a local mapping of the shared memory containing the
82 // encoded audio data, and save the contents to the temporary file.
83 base::SharedMemory encoded_data(encoded_audio_handle_, true);
84
85 if (!encoded_data.Map(data_size_)) {
86 VLOG(0) << "Unable to map shared memory!";
87 return -1;
88 }
89
90 if (static_cast<uint32_t>(write(fd.get(), encoded_data.memory(), data_size_))
91 != data_size_) {
92 VLOG(0) << "Failed to write all audio data to temp file!";
93 return -1;
94 }
95
96 lseek(fd.get(), 0, SEEK_SET);
97
98 return fd.release();
99 }
100
101 bool WebAudioMediaCodecBridge::DecodeInMemoryAudioFile() {
102 JNIEnv* env = AttachCurrentThread();
103 CHECK(env);
104
105 jobject context = base::android::GetApplicationContext();
106
107 int sourceFd = SaveEncodedAudioToFile(env, context);
108
109 if (sourceFd < 0)
110 return false;
111
112 jboolean decoded = Java_WebAudioMediaCodecBridge_decodeAudioFile(
113 env,
114 context,
115 reinterpret_cast<intptr_t>(this),
116 sourceFd,
117 data_size_);
118
119 close(sourceFd);
120
121 DVLOG(1) << "decoded = " << (decoded ? "true" : "false");
122
123 return decoded;
124 }
125
126 void WebAudioMediaCodecBridge::InitializeDestination(
127 JNIEnv* env,
128 const JavaParamRef<jobject>& /*java object*/,
129 jint channel_count,
130 jint sample_rate,
131 jlong duration_microsec) {
132 // Send information about this audio file: number of channels,
133 // sample rate (Hz), and the number of frames.
134 struct WebAudioMediaCodecInfo info = {
135 static_cast<unsigned long>(channel_count),
136 static_cast<unsigned long>(sample_rate),
137 // The number of frames is the duration of the file
138 // (in microseconds) times the sample rate.
139 static_cast<unsigned long>(
140 0.5 + (duration_microsec * 0.000001 *
141 sample_rate))
142 };
143
144 DVLOG(1) << "InitializeDestination:"
145 << " channel count = " << channel_count
146 << " rate = " << sample_rate
147 << " duration = " << duration_microsec << " microsec";
148
149 HANDLE_EINTR(write(pcm_output_, &info, sizeof(info)));
150 }
151
152 void WebAudioMediaCodecBridge::OnChunkDecoded(
153 JNIEnv* env,
154 const JavaParamRef<jobject>& /*java object*/,
155 const JavaParamRef<jobject>& buf,
156 jint buf_size,
157 jint input_channel_count,
158 jint output_channel_count) {
159 if (buf_size <= 0 || !buf)
160 return;
161
162 int8_t* buffer =
163 static_cast<int8_t*>(env->GetDirectBufferAddress(buf));
164 size_t count = static_cast<size_t>(buf_size);
165 std::vector<int16_t> decoded_data;
166
167 if (input_channel_count == 1 && output_channel_count == 2) {
168 // See crbug.com/266006. The file has one channel, but the
169 // decoder decided to return two channels. To be consistent with
170 // the number of channels in the file, only send one channel (the
171 // first).
172 int16_t* data = static_cast<int16_t*>(env->GetDirectBufferAddress(buf));
173 int frame_count = buf_size / sizeof(*data) / 2;
174
175 decoded_data.resize(frame_count);
176 for (int k = 0; k < frame_count; ++k) {
177 decoded_data[k] = *data;
178 data += 2;
179 }
180 buffer = reinterpret_cast<int8_t*>(decoded_data.data());
181 DCHECK(buffer);
182 count = frame_count * sizeof(*data);
183 }
184
185 // Write out the data to the pipe in small chunks if necessary.
186 while (count > 0) {
187 int bytes_to_write = (count >= PIPE_BUF) ? PIPE_BUF : count;
188 ssize_t bytes_written = HANDLE_EINTR(write(pcm_output_,
189 buffer,
190 bytes_to_write));
191 if (bytes_written == -1)
192 break;
193 count -= bytes_written;
194 buffer += bytes_written;
195 }
196 }
197
198 bool WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge(JNIEnv* env) {
199 return RegisterNativesImpl(env);
200 }
201
202 } // namespace
OLDNEW
« no previous file with comments | « media/base/android/webaudio_media_codec_bridge.h ('k') | media/base/android/webaudio_media_codec_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698