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

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

Issue 2624213006: media: Fix MojoAudioDecoder reinitialization (Closed)
Patch Set: drop extra flags 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_.is_bound())
49 remote_decoder_.Bind(std::move(remote_decoder_info_)); 47 BindRemoteDecoder();
48
49 // This could happen during reinitialization.
50 if (remote_decoder_.encountered_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 (remote_decoder_.encountered_error()) {
87 task_runner_->PostTask(FROM_HERE, 81 task_runner_->PostTask(FROM_HERE,
88 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR)); 82 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR));
89 return; 83 return;
90 } 84 }
91 85
92 mojom::DecoderBufferPtr buffer = 86 mojom::DecoderBufferPtr buffer =
93 mojo_decoder_buffer_writer_->WriteDecoderBuffer(media_buffer); 87 mojo_decoder_buffer_writer_->WriteDecoderBuffer(media_buffer);
94 if (!buffer) { 88 if (!buffer) {
95 task_runner_->PostTask(FROM_HERE, 89 task_runner_->PostTask(FROM_HERE,
96 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR)); 90 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR));
97 return; 91 return;
98 } 92 }
99 93
100 DCHECK(decode_cb_.is_null()); 94 DCHECK(decode_cb_.is_null());
101 decode_cb_ = decode_cb; 95 decode_cb_ = decode_cb;
102 96
103 remote_decoder_->Decode( 97 remote_decoder_->Decode(
104 std::move(buffer), 98 std::move(buffer),
105 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); 99 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this)));
106 } 100 }
107 101
108 void MojoAudioDecoder::Reset(const base::Closure& closure) { 102 void MojoAudioDecoder::Reset(const base::Closure& closure) {
109 DVLOG(2) << __func__; 103 DVLOG(2) << __func__;
110 DCHECK(task_runner_->BelongsToCurrentThread()); 104 DCHECK(task_runner_->BelongsToCurrentThread());
111 105
112 if (has_connection_error_) { 106 if (remote_decoder_.encountered_error()) {
113 if (!decode_cb_.is_null()) { 107 if (!decode_cb_.is_null()) {
114 task_runner_->PostTask(FROM_HERE, 108 task_runner_->PostTask(FROM_HERE,
115 base::Bind(base::ResetAndReturn(&decode_cb_), 109 base::Bind(base::ResetAndReturn(&decode_cb_),
116 DecodeStatus::DECODE_ERROR)); 110 DecodeStatus::DECODE_ERROR));
117 } 111 }
118 112
119 task_runner_->PostTask(FROM_HERE, closure); 113 task_runner_->PostTask(FROM_HERE, closure);
120 return; 114 return;
121 } 115 }
122 116
123 DCHECK(reset_cb_.is_null()); 117 DCHECK(reset_cb_.is_null());
124 reset_cb_ = closure; 118 reset_cb_ = closure;
125 remote_decoder_->Reset( 119 remote_decoder_->Reset(
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_.is_bound());
dcheng 2017/01/19 00:43:57 FWIW, this DCHECK and the DCHECK on line 136 are i
xhwang 2017/01/19 18:30:39 Done.
134
135 remote_decoder_.Bind(std::move(remote_decoder_info_));
136 DCHECK(remote_decoder_.is_bound());
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());
146 159 DCHECK(remote_decoder_.encountered_error());
147 has_connection_error_ = true;
148 160
149 if (!init_cb_.is_null()) { 161 if (!init_cb_.is_null()) {
150 base::ResetAndReturn(&init_cb_).Run(false); 162 base::ResetAndReturn(&init_cb_).Run(false);
151 return; 163 return;
152 } 164 }
153 165
154 if (!decode_cb_.is_null()) 166 if (!decode_cb_.is_null())
155 base::ResetAndReturn(&decode_cb_).Run(DecodeStatus::DECODE_ERROR); 167 base::ResetAndReturn(&decode_cb_).Run(DecodeStatus::DECODE_ERROR);
156 if (!reset_cb_.is_null()) 168 if (!reset_cb_.is_null())
157 base::ResetAndReturn(&reset_cb_).Run(); 169 base::ResetAndReturn(&reset_cb_).Run();
158 } 170 }
159 171
160 void MojoAudioDecoder::OnInitialized(bool success, 172 void MojoAudioDecoder::OnInitialized(bool success,
161 bool needs_bitstream_conversion) { 173 bool needs_bitstream_conversion) {
162 DVLOG(1) << __func__ << ": success:" << success; 174 DVLOG(1) << __func__ << ": success:" << success;
163 DCHECK(task_runner_->BelongsToCurrentThread()); 175 DCHECK(task_runner_->BelongsToCurrentThread());
164 176
165 needs_bitstream_conversion_ = needs_bitstream_conversion; 177 needs_bitstream_conversion_ = needs_bitstream_conversion;
166 178
167 if (success) { 179 if (success && !mojo_decoder_buffer_writer_) {
168 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; 180 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle;
169 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create( 181 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create(
170 DemuxerStream::AUDIO, &remote_consumer_handle); 182 DemuxerStream::AUDIO, &remote_consumer_handle);
171 // Pass consumer end to |remote_decoder_|. 183 // Pass consumer end to |remote_decoder_|.
172 remote_decoder_->SetDataSource(std::move(remote_consumer_handle)); 184 remote_decoder_->SetDataSource(std::move(remote_consumer_handle));
173 } 185 }
174 186
175 base::ResetAndReturn(&init_cb_).Run(success); 187 base::ResetAndReturn(&init_cb_).Run(success);
176 } 188 }
177 189
(...skipping 10 matching lines...) Expand all
188 DCHECK(task_runner_->BelongsToCurrentThread()); 200 DCHECK(task_runner_->BelongsToCurrentThread());
189 201
190 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). 202 // For pending decodes OnDecodeStatus() should arrive before OnResetDone().
191 DCHECK(decode_cb_.is_null()); 203 DCHECK(decode_cb_.is_null());
192 204
193 DCHECK(!reset_cb_.is_null()); 205 DCHECK(!reset_cb_.is_null());
194 base::ResetAndReturn(&reset_cb_).Run(); 206 base::ResetAndReturn(&reset_cb_).Run();
195 } 207 }
196 208
197 } // namespace media 209 } // 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