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

Side by Side Diff: media/mojo/clients/mojo_audio_decoder.cc

Issue 2624213006: media: Fix MojoAudioDecoder reinitialization (Closed)
Patch Set: Created 3 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
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
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
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
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
OLDNEW
« no previous file with comments | « media/mojo/clients/mojo_audio_decoder.h ('k') | media/mojo/clients/mojo_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698