OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/mojo/services/mojo_audio_decoder.h" | 5 #include "media/mojo/services/mojo_audio_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
| 14 #include "media/base/audio_buffer.h" |
14 #include "media/base/cdm_context.h" | 15 #include "media/base/cdm_context.h" |
15 #include "media/mojo/common/media_type_converters.h" | 16 #include "media/mojo/common/media_type_converters.h" |
16 | 17 |
17 namespace media { | 18 namespace media { |
18 | 19 |
19 MojoAudioDecoder::MojoAudioDecoder( | 20 MojoAudioDecoder::MojoAudioDecoder( |
20 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 21 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
21 interfaces::AudioDecoderPtr remote_decoder) | 22 interfaces::AudioDecoderPtr remote_decoder) |
22 : task_runner_(task_runner), | 23 : task_runner_(task_runner), |
23 remote_decoder_(std::move(remote_decoder)), | 24 remote_decoder_(std::move(remote_decoder)), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 return; | 59 return; |
59 } | 60 } |
60 | 61 |
61 // Otherwise, set an error handler to catch the connection error. | 62 // Otherwise, set an error handler to catch the connection error. |
62 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | 63 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, |
63 // and the error handler can't be invoked once |remote_decoder_| is destroyed. | 64 // and the error handler can't be invoked once |remote_decoder_| is destroyed. |
64 remote_decoder_.set_connection_error_handler( | 65 remote_decoder_.set_connection_error_handler( |
65 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); | 66 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); |
66 | 67 |
67 init_cb_ = init_cb; | 68 init_cb_ = init_cb; |
| 69 output_cb_ = output_cb; |
68 | 70 |
69 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | 71 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, |
70 // and the callback won't be dispatched if |remote_decoder_| is destroyed. | 72 // and the callback won't be dispatched if |remote_decoder_| is destroyed. |
71 remote_decoder_->Initialize( | 73 remote_decoder_->Initialize( |
72 binding_.CreateInterfacePtrAndBind(), | 74 binding_.CreateInterfacePtrAndBind(), |
73 interfaces::AudioDecoderConfig::From(config), cdm_id, | 75 interfaces::AudioDecoderConfig::From(config), cdm_id, |
74 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); | 76 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); |
75 } | 77 } |
76 | 78 |
77 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 79 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
78 const DecodeCB& decode_cb) { | 80 const DecodeCB& decode_cb) { |
79 DVLOG(3) << __FUNCTION__; | 81 DVLOG(3) << __FUNCTION__; |
80 DCHECK(task_runner_->BelongsToCurrentThread()); | 82 DCHECK(task_runner_->BelongsToCurrentThread()); |
81 | 83 |
82 if (has_connection_error_) { | 84 if (has_connection_error_) { |
83 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); | 85 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); |
84 return; | 86 return; |
85 } | 87 } |
86 | 88 |
87 DCHECK(decode_cb_.is_null()); | 89 DCHECK(decode_cb_.is_null()); |
88 decode_cb_ = decode_cb; | 90 decode_cb_ = decode_cb; |
89 | 91 |
90 // This code won't work because |buffer| is not serialized. | |
91 // TODO(timav): Serialize DecodeBuffer into data pipe. | |
92 remote_decoder_->Decode( | 92 remote_decoder_->Decode( |
93 interfaces::DecoderBuffer::From(buffer), | 93 TransferDecoderBuffer(buffer), |
94 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); | 94 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); |
95 } | 95 } |
96 | 96 |
97 void MojoAudioDecoder::Reset(const base::Closure& closure) { | 97 void MojoAudioDecoder::Reset(const base::Closure& closure) { |
98 DVLOG(2) << __FUNCTION__; | 98 DVLOG(2) << __FUNCTION__; |
99 DCHECK(task_runner_->BelongsToCurrentThread()); | 99 DCHECK(task_runner_->BelongsToCurrentThread()); |
100 | 100 |
101 if (has_connection_error_) { | 101 if (has_connection_error_) { |
102 if (!decode_cb_.is_null()) { | 102 if (!decode_cb_.is_null()) { |
103 task_runner_->PostTask( | 103 task_runner_->PostTask( |
(...skipping 15 matching lines...) Expand all Loading... |
119 DVLOG(1) << __FUNCTION__; | 119 DVLOG(1) << __FUNCTION__; |
120 DCHECK(task_runner_->BelongsToCurrentThread()); | 120 DCHECK(task_runner_->BelongsToCurrentThread()); |
121 | 121 |
122 return needs_bitstream_conversion_; | 122 return needs_bitstream_conversion_; |
123 } | 123 } |
124 | 124 |
125 void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { | 125 void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { |
126 DVLOG(1) << __FUNCTION__; | 126 DVLOG(1) << __FUNCTION__; |
127 DCHECK(task_runner_->BelongsToCurrentThread()); | 127 DCHECK(task_runner_->BelongsToCurrentThread()); |
128 | 128 |
129 NOTIMPLEMENTED(); | 129 output_cb_.Run(buffer.To<scoped_refptr<AudioBuffer>>()); |
130 } | 130 } |
131 | 131 |
132 void MojoAudioDecoder::OnConnectionError() { | 132 void MojoAudioDecoder::OnConnectionError() { |
133 DVLOG(1) << __FUNCTION__; | 133 DVLOG(1) << __FUNCTION__; |
134 DCHECK(task_runner_->BelongsToCurrentThread()); | 134 DCHECK(task_runner_->BelongsToCurrentThread()); |
135 | 135 |
136 has_connection_error_ = true; | 136 has_connection_error_ = true; |
137 | 137 |
138 if (!init_cb_.is_null()) { | 138 if (!init_cb_.is_null()) { |
139 base::ResetAndReturn(&init_cb_).Run(false); | 139 base::ResetAndReturn(&init_cb_).Run(false); |
140 return; | 140 return; |
141 } | 141 } |
142 | 142 |
143 if (!decode_cb_.is_null()) | 143 if (!decode_cb_.is_null()) |
144 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | 144 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); |
145 if (!reset_cb_.is_null()) | 145 if (!reset_cb_.is_null()) |
146 base::ResetAndReturn(&reset_cb_).Run(); | 146 base::ResetAndReturn(&reset_cb_).Run(); |
147 } | 147 } |
148 | 148 |
149 void MojoAudioDecoder::OnInitialized(bool status, | 149 void MojoAudioDecoder::OnInitialized(bool status, |
150 bool needs_bitstream_conversion) { | 150 bool needs_bitstream_conversion) { |
151 DVLOG(1) << __FUNCTION__ << ": status:" << status; | 151 DVLOG(1) << __FUNCTION__ << ": status:" << status; |
152 DCHECK(task_runner_->BelongsToCurrentThread()); | 152 DCHECK(task_runner_->BelongsToCurrentThread()); |
153 | 153 |
154 needs_bitstream_conversion_ = needs_bitstream_conversion; | 154 needs_bitstream_conversion_ = needs_bitstream_conversion; |
155 | 155 |
| 156 if (status) |
| 157 CreateDataPipe(); |
| 158 |
156 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); | 159 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); |
157 } | 160 } |
158 | 161 |
159 static media::AudioDecoder::Status ConvertDecodeStatus( | 162 static media::AudioDecoder::Status ConvertDecodeStatus( |
160 interfaces::AudioDecoder::DecodeStatus status) { | 163 interfaces::AudioDecoder::DecodeStatus status) { |
161 switch (status) { | 164 switch (status) { |
162 case interfaces::AudioDecoder::DecodeStatus::OK: | 165 case interfaces::AudioDecoder::DecodeStatus::OK: |
163 return media::AudioDecoder::kOk; | 166 return media::AudioDecoder::kOk; |
164 case interfaces::AudioDecoder::DecodeStatus::ABORTED: | 167 case interfaces::AudioDecoder::DecodeStatus::ABORTED: |
165 return media::AudioDecoder::kAborted; | 168 return media::AudioDecoder::kAborted; |
(...skipping 17 matching lines...) Expand all Loading... |
183 DVLOG(1) << __FUNCTION__; | 186 DVLOG(1) << __FUNCTION__; |
184 DCHECK(task_runner_->BelongsToCurrentThread()); | 187 DCHECK(task_runner_->BelongsToCurrentThread()); |
185 | 188 |
186 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). | 189 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). |
187 DCHECK(decode_cb_.is_null()); | 190 DCHECK(decode_cb_.is_null()); |
188 | 191 |
189 DCHECK(!reset_cb_.is_null()); | 192 DCHECK(!reset_cb_.is_null()); |
190 base::ResetAndReturn(&reset_cb_).Run(); | 193 base::ResetAndReturn(&reset_cb_).Run(); |
191 } | 194 } |
192 | 195 |
| 196 void MojoAudioDecoder::CreateDataPipe() { |
| 197 MojoCreateDataPipeOptions options; |
| 198 options.struct_size = sizeof(MojoCreateDataPipeOptions); |
| 199 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
| 200 options.element_num_bytes = 1; |
| 201 // TODO(timav): Consider capacity calculation based on AudioDecoderConfig. |
| 202 options.capacity_num_bytes = 512 * 1024; |
| 203 |
| 204 mojo::DataPipe write_pipe(options); |
| 205 |
| 206 // Keep producer end. |
| 207 producer_handle_ = std::move(write_pipe.producer_handle); |
| 208 |
| 209 // Pass consumer end to |remote_decoder_|. |
| 210 remote_decoder_->SetDataSource(std::move(write_pipe.consumer_handle)); |
| 211 } |
| 212 |
| 213 interfaces::DecoderBufferPtr MojoAudioDecoder::TransferDecoderBuffer( |
| 214 const scoped_refptr<DecoderBuffer>& media_buffer) { |
| 215 interfaces::DecoderBufferPtr buffer = |
| 216 interfaces::DecoderBuffer::From(media_buffer); |
| 217 if (media_buffer->end_of_stream()) |
| 218 return buffer; |
| 219 |
| 220 // Serialize the data section of the DecoderBuffer into our pipe. |
| 221 uint32_t num_bytes = base::checked_cast<uint32_t>(media_buffer->data_size()); |
| 222 DCHECK_GT(num_bytes, 0u); |
| 223 CHECK_EQ(WriteDataRaw(producer_handle_.get(), media_buffer->data(), |
| 224 &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE), |
| 225 MOJO_RESULT_OK); |
| 226 CHECK_EQ(num_bytes, static_cast<uint32_t>(media_buffer->data_size())); |
| 227 return buffer; |
| 228 } |
| 229 |
193 } // namespace media | 230 } // namespace media |
OLD | NEW |