Chromium Code Reviews| 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/clients/mojo_audio_decoder.h" | 5 #include "media/mojo/clients/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/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "media/base/audio_buffer.h" | 14 #include "media/base/audio_buffer.h" |
| 15 #include "media/base/cdm_context.h" | 15 #include "media/base/cdm_context.h" |
| 16 #include "media/base/demuxer_stream.h" | 16 #include "media/base/demuxer_stream.h" |
| 17 #include "media/mojo/common/media_type_converters.h" | 17 #include "media/mojo/common/media_type_converters.h" |
| 18 #include "media/mojo/common/mojo_decoder_buffer_converter.h" | 18 #include "media/mojo/common/mojo_decoder_buffer_converter.h" |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 | 21 |
| 22 MojoAudioDecoder::MojoAudioDecoder( | 22 MojoAudioDecoder::MojoAudioDecoder( |
| 23 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 23 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 24 mojom::AudioDecoderPtr remote_decoder) | 24 mojom::AudioDecoderPtr remote_decoder) |
| 25 : task_runner_(task_runner), | 25 : task_runner_(task_runner), |
| 26 remote_decoder_info_(remote_decoder.PassInterface()), | 26 remote_decoder_info_(remote_decoder.PassInterface()), |
| 27 client_binding_(this), | 27 client_binding_(this) { |
| 28 has_connection_error_(false), | |
| 29 needs_bitstream_conversion_(false) { | |
| 30 DVLOG(1) << __func__; | 28 DVLOG(1) << __func__; |
| 31 } | 29 } |
| 32 | 30 |
| 33 MojoAudioDecoder::~MojoAudioDecoder() { | 31 MojoAudioDecoder::~MojoAudioDecoder() { |
| 34 DVLOG(1) << __func__; | 32 DVLOG(1) << __func__; |
| 35 } | 33 } |
| 36 | 34 |
| 37 std::string MojoAudioDecoder::GetDisplayName() const { | 35 std::string MojoAudioDecoder::GetDisplayName() const { |
| 38 return "MojoAudioDecoder"; | 36 return "MojoAudioDecoder"; |
| 39 } | 37 } |
| 40 | 38 |
| 41 void MojoAudioDecoder::Initialize(const AudioDecoderConfig& config, | 39 void MojoAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 42 CdmContext* cdm_context, | 40 CdmContext* cdm_context, |
| 43 const InitCB& init_cb, | 41 const InitCB& init_cb, |
| 44 const OutputCB& output_cb) { | 42 const OutputCB& output_cb) { |
| 45 DVLOG(1) << __func__; | 43 DVLOG(1) << __func__; |
| 46 DCHECK(task_runner_->BelongsToCurrentThread()); | 44 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 47 | 45 |
| 48 // Bind |remote_decoder_| to the |task_runner_|. | 46 if (!remote_decoder_bound_) |
|
dcheng
2017/01/17 19:48:10
One thing I'd like to understand is why we have th
sandersd (OOO until July 31)
2017/01/17 20:03:05
In this case (and also the code it is copied from)
sandersd (OOO until July 31)
2017/01/17 20:12:28
After reading through the implementation, I'm not
dcheng
2017/01/18 01:39:18
I confirmed with the mojo team, but a connection e
xhwang
2017/01/18 21:46:58
Thanks for the suggestions. This makes sense to me
| |
| 49 remote_decoder_.Bind(std::move(remote_decoder_info_)); | 47 BindRemoteDecoder(); |
| 48 | |
| 49 // This could happen during reinitialization. | |
| 50 if (has_connection_error_) { | |
| 51 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); | |
| 52 return; | |
| 53 } | |
| 50 | 54 |
| 51 // Fail immediately if the stream is encrypted but |cdm_context| is invalid. | 55 // Fail immediately if the stream is encrypted but |cdm_context| is invalid. |
| 52 int cdm_id = (config.is_encrypted() && cdm_context) | 56 int cdm_id = (config.is_encrypted() && cdm_context) |
| 53 ? cdm_context->GetCdmId() | 57 ? cdm_context->GetCdmId() |
| 54 : CdmContext::kInvalidCdmId; | 58 : CdmContext::kInvalidCdmId; |
| 55 | 59 |
| 56 if (config.is_encrypted() && CdmContext::kInvalidCdmId == cdm_id) { | 60 if (config.is_encrypted() && CdmContext::kInvalidCdmId == cdm_id) { |
| 57 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); | 61 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); |
| 58 return; | 62 return; |
| 59 } | 63 } |
| 60 | 64 |
| 61 // Otherwise, set an error handler to catch the connection error. | |
| 62 // 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 remote_decoder_.set_connection_error_handler( | |
| 65 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); | |
| 66 | |
| 67 init_cb_ = init_cb; | 65 init_cb_ = init_cb; |
| 68 output_cb_ = output_cb; | 66 output_cb_ = output_cb; |
| 69 | 67 |
| 70 mojom::AudioDecoderClientAssociatedPtrInfo client_ptr_info; | |
| 71 client_binding_.Bind(&client_ptr_info, remote_decoder_.associated_group()); | |
| 72 | |
| 73 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | 68 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, |
| 74 // and the callback won't be dispatched if |remote_decoder_| is destroyed. | 69 // and the callback won't be dispatched if |remote_decoder_| is destroyed. |
| 75 remote_decoder_->Initialize( | 70 remote_decoder_->Initialize( |
| 76 std::move(client_ptr_info), mojom::AudioDecoderConfig::From(config), | 71 mojom::AudioDecoderConfig::From(config), cdm_id, |
| 77 cdm_id, | |
| 78 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); | 72 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); |
| 79 } | 73 } |
| 80 | 74 |
| 81 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& media_buffer, | 75 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& media_buffer, |
| 82 const DecodeCB& decode_cb) { | 76 const DecodeCB& decode_cb) { |
| 83 DVLOG(3) << __func__; | 77 DVLOG(3) << __func__; |
| 84 DCHECK(task_runner_->BelongsToCurrentThread()); | 78 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 85 | 79 |
| 86 if (has_connection_error_) { | 80 if (has_connection_error_) { |
| 87 task_runner_->PostTask(FROM_HERE, | 81 task_runner_->PostTask(FROM_HERE, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 base::Bind(&MojoAudioDecoder::OnResetDone, base::Unretained(this))); | 120 base::Bind(&MojoAudioDecoder::OnResetDone, base::Unretained(this))); |
| 127 } | 121 } |
| 128 | 122 |
| 129 bool MojoAudioDecoder::NeedsBitstreamConversion() const { | 123 bool MojoAudioDecoder::NeedsBitstreamConversion() const { |
| 130 DVLOG(1) << __func__; | 124 DVLOG(1) << __func__; |
| 131 DCHECK(task_runner_->BelongsToCurrentThread()); | 125 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 132 | 126 |
| 133 return needs_bitstream_conversion_; | 127 return needs_bitstream_conversion_; |
| 134 } | 128 } |
| 135 | 129 |
| 130 void MojoAudioDecoder::BindRemoteDecoder() { | |
| 131 DVLOG(1) << __func__; | |
| 132 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 133 DCHECK(!remote_decoder_bound_); | |
| 134 | |
| 135 remote_decoder_bound_ = true; | |
| 136 remote_decoder_.Bind(std::move(remote_decoder_info_)); | |
| 137 | |
| 138 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | |
| 139 // and the error handler can't be invoked once |remote_decoder_| is destroyed. | |
| 140 remote_decoder_.set_connection_error_handler( | |
| 141 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); | |
| 142 | |
| 143 mojom::AudioDecoderClientAssociatedPtrInfo client_ptr_info; | |
| 144 client_binding_.Bind(&client_ptr_info, remote_decoder_.associated_group()); | |
| 145 | |
| 146 remote_decoder_->Construct(std::move(client_ptr_info)); | |
| 147 } | |
| 148 | |
| 136 void MojoAudioDecoder::OnBufferDecoded(mojom::AudioBufferPtr buffer) { | 149 void MojoAudioDecoder::OnBufferDecoded(mojom::AudioBufferPtr buffer) { |
| 137 DVLOG(1) << __func__; | 150 DVLOG(1) << __func__; |
| 138 DCHECK(task_runner_->BelongsToCurrentThread()); | 151 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 139 | 152 |
| 140 output_cb_.Run(buffer.To<scoped_refptr<AudioBuffer>>()); | 153 output_cb_.Run(buffer.To<scoped_refptr<AudioBuffer>>()); |
| 141 } | 154 } |
| 142 | 155 |
| 143 void MojoAudioDecoder::OnConnectionError() { | 156 void MojoAudioDecoder::OnConnectionError() { |
| 144 DVLOG(1) << __func__; | 157 DVLOG(1) << __func__; |
| 145 DCHECK(task_runner_->BelongsToCurrentThread()); | 158 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 157 base::ResetAndReturn(&reset_cb_).Run(); | 170 base::ResetAndReturn(&reset_cb_).Run(); |
| 158 } | 171 } |
| 159 | 172 |
| 160 void MojoAudioDecoder::OnInitialized(bool success, | 173 void MojoAudioDecoder::OnInitialized(bool success, |
| 161 bool needs_bitstream_conversion) { | 174 bool needs_bitstream_conversion) { |
| 162 DVLOG(1) << __func__ << ": success:" << success; | 175 DVLOG(1) << __func__ << ": success:" << success; |
| 163 DCHECK(task_runner_->BelongsToCurrentThread()); | 176 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 164 | 177 |
| 165 needs_bitstream_conversion_ = needs_bitstream_conversion; | 178 needs_bitstream_conversion_ = needs_bitstream_conversion; |
| 166 | 179 |
| 167 if (success) { | 180 if (success && !mojo_decoder_buffer_writer_) { |
| 168 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; | 181 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; |
| 169 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create( | 182 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create( |
| 170 DemuxerStream::AUDIO, &remote_consumer_handle); | 183 DemuxerStream::AUDIO, &remote_consumer_handle); |
| 171 // Pass consumer end to |remote_decoder_|. | 184 // Pass consumer end to |remote_decoder_|. |
| 172 remote_decoder_->SetDataSource(std::move(remote_consumer_handle)); | 185 remote_decoder_->SetDataSource(std::move(remote_consumer_handle)); |
| 173 } | 186 } |
| 174 | 187 |
| 175 base::ResetAndReturn(&init_cb_).Run(success); | 188 base::ResetAndReturn(&init_cb_).Run(success); |
| 176 } | 189 } |
| 177 | 190 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 188 DCHECK(task_runner_->BelongsToCurrentThread()); | 201 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 189 | 202 |
| 190 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). | 203 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). |
| 191 DCHECK(decode_cb_.is_null()); | 204 DCHECK(decode_cb_.is_null()); |
| 192 | 205 |
| 193 DCHECK(!reset_cb_.is_null()); | 206 DCHECK(!reset_cb_.is_null()); |
| 194 base::ResetAndReturn(&reset_cb_).Run(); | 207 base::ResetAndReturn(&reset_cb_).Run(); |
| 195 } | 208 } |
| 196 | 209 |
| 197 } // namespace media | 210 } // namespace media |
| OLD | NEW |