| 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 |