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" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 return; | 58 return; |
59 } | 59 } |
60 | 60 |
61 // Otherwise, set an error handler to catch the connection error. | 61 // Otherwise, set an error handler to catch the connection error. |
62 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | 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. | 63 // and the error handler can't be invoked once |remote_decoder_| is destroyed. |
64 remote_decoder_.set_connection_error_handler( | 64 remote_decoder_.set_connection_error_handler( |
65 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); | 65 base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); |
66 | 66 |
67 init_cb_ = init_cb; | 67 init_cb_ = init_cb; |
68 | 68 |
xhwang
2016/03/19 04:57:25
Can we call CreateDataPipe() here and pass the |re
| |
69 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, | 69 // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, |
70 // and the callback won't be dispatched if |remote_decoder_| is destroyed. | 70 // and the callback won't be dispatched if |remote_decoder_| is destroyed. |
71 remote_decoder_->Initialize( | 71 remote_decoder_->Initialize( |
72 binding_.CreateInterfacePtrAndBind(), | 72 binding_.CreateInterfacePtrAndBind(), |
73 interfaces::AudioDecoderConfig::From(config), cdm_id, | 73 interfaces::AudioDecoderConfig::From(config), cdm_id, |
74 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); | 74 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); |
75 } | 75 } |
76 | 76 |
77 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 77 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
78 const DecodeCB& decode_cb) { | 78 const DecodeCB& decode_cb) { |
79 DVLOG(3) << __FUNCTION__; | 79 DVLOG(3) << __FUNCTION__; |
80 DCHECK(task_runner_->BelongsToCurrentThread()); | 80 DCHECK(task_runner_->BelongsToCurrentThread()); |
81 | 81 |
82 if (has_connection_error_) { | 82 if (has_connection_error_) { |
83 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); | 83 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); |
84 return; | 84 return; |
85 } | 85 } |
86 | 86 |
87 DCHECK(decode_cb_.is_null()); | 87 DCHECK(decode_cb_.is_null()); |
88 decode_cb_ = decode_cb; | 88 decode_cb_ = decode_cb; |
89 | 89 |
90 // This code won't work because |buffer| is not serialized. | |
91 // TODO(timav): Serialize DecodeBuffer into data pipe. | |
92 remote_decoder_->Decode( | 90 remote_decoder_->Decode( |
93 interfaces::DecoderBuffer::From(buffer), | 91 TransferDecoderBuffer(buffer), |
94 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); | 92 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); |
95 } | 93 } |
96 | 94 |
97 void MojoAudioDecoder::Reset(const base::Closure& closure) { | 95 void MojoAudioDecoder::Reset(const base::Closure& closure) { |
98 DVLOG(2) << __FUNCTION__; | 96 DVLOG(2) << __FUNCTION__; |
99 DCHECK(task_runner_->BelongsToCurrentThread()); | 97 DCHECK(task_runner_->BelongsToCurrentThread()); |
100 | 98 |
101 if (has_connection_error_) { | 99 if (has_connection_error_) { |
102 if (!decode_cb_.is_null()) { | 100 if (!decode_cb_.is_null()) { |
103 task_runner_->PostTask( | 101 task_runner_->PostTask( |
(...skipping 15 matching lines...) Expand all Loading... | |
119 DVLOG(1) << __FUNCTION__; | 117 DVLOG(1) << __FUNCTION__; |
120 DCHECK(task_runner_->BelongsToCurrentThread()); | 118 DCHECK(task_runner_->BelongsToCurrentThread()); |
121 | 119 |
122 return needs_bitstream_conversion_; | 120 return needs_bitstream_conversion_; |
123 } | 121 } |
124 | 122 |
125 void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { | 123 void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { |
126 DVLOG(1) << __FUNCTION__; | 124 DVLOG(1) << __FUNCTION__; |
127 DCHECK(task_runner_->BelongsToCurrentThread()); | 125 DCHECK(task_runner_->BelongsToCurrentThread()); |
128 | 126 |
129 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
xhwang
2016/03/19 04:57:25
You can finish this now, it should just be:
outpu
Tima Vaisburd
2016/03/19 22:04:46
Great, I will try that. There is a question though
xhwang
2016/03/20 16:15:57
We can do that later. It's marked as a P3 in our d
Tima Vaisburd
2016/03/21 19:08:26
Done.
| |
130 } | 128 } |
131 | 129 |
132 void MojoAudioDecoder::OnConnectionError() { | 130 void MojoAudioDecoder::OnConnectionError() { |
133 DVLOG(1) << __FUNCTION__; | 131 DVLOG(1) << __FUNCTION__; |
134 DCHECK(task_runner_->BelongsToCurrentThread()); | 132 DCHECK(task_runner_->BelongsToCurrentThread()); |
135 | 133 |
136 has_connection_error_ = true; | 134 has_connection_error_ = true; |
137 | 135 |
138 if (!init_cb_.is_null()) { | 136 if (!init_cb_.is_null()) { |
139 base::ResetAndReturn(&init_cb_).Run(false); | 137 base::ResetAndReturn(&init_cb_).Run(false); |
140 return; | 138 return; |
141 } | 139 } |
142 | 140 |
143 if (!decode_cb_.is_null()) | 141 if (!decode_cb_.is_null()) |
144 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | 142 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); |
145 if (!reset_cb_.is_null()) | 143 if (!reset_cb_.is_null()) |
146 base::ResetAndReturn(&reset_cb_).Run(); | 144 base::ResetAndReturn(&reset_cb_).Run(); |
147 } | 145 } |
148 | 146 |
149 void MojoAudioDecoder::OnInitialized(bool status, | 147 void MojoAudioDecoder::OnInitialized(bool status, |
150 bool needs_bitstream_conversion) { | 148 bool needs_bitstream_conversion) { |
151 DVLOG(1) << __FUNCTION__ << ": status:" << status; | 149 DVLOG(1) << __FUNCTION__ << ": status:" << status; |
152 DCHECK(task_runner_->BelongsToCurrentThread()); | 150 DCHECK(task_runner_->BelongsToCurrentThread()); |
153 | 151 |
154 needs_bitstream_conversion_ = needs_bitstream_conversion; | 152 needs_bitstream_conversion_ = needs_bitstream_conversion; |
155 | 153 |
154 if (status) | |
155 CreateDataPipe(); | |
156 | |
156 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); | 157 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); |
157 } | 158 } |
158 | 159 |
159 static media::AudioDecoder::Status ConvertDecodeStatus( | 160 static media::AudioDecoder::Status ConvertDecodeStatus( |
160 interfaces::AudioDecoder::DecodeStatus status) { | 161 interfaces::AudioDecoder::DecodeStatus status) { |
161 switch (status) { | 162 switch (status) { |
162 case interfaces::AudioDecoder::DecodeStatus::OK: | 163 case interfaces::AudioDecoder::DecodeStatus::OK: |
163 return media::AudioDecoder::kOk; | 164 return media::AudioDecoder::kOk; |
164 case interfaces::AudioDecoder::DecodeStatus::ABORTED: | 165 case interfaces::AudioDecoder::DecodeStatus::ABORTED: |
165 return media::AudioDecoder::kAborted; | 166 return media::AudioDecoder::kAborted; |
(...skipping 17 matching lines...) Expand all Loading... | |
183 DVLOG(1) << __FUNCTION__; | 184 DVLOG(1) << __FUNCTION__; |
184 DCHECK(task_runner_->BelongsToCurrentThread()); | 185 DCHECK(task_runner_->BelongsToCurrentThread()); |
185 | 186 |
186 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). | 187 // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). |
187 DCHECK(decode_cb_.is_null()); | 188 DCHECK(decode_cb_.is_null()); |
188 | 189 |
189 DCHECK(!reset_cb_.is_null()); | 190 DCHECK(!reset_cb_.is_null()); |
190 base::ResetAndReturn(&reset_cb_).Run(); | 191 base::ResetAndReturn(&reset_cb_).Run(); |
191 } | 192 } |
192 | 193 |
194 void MojoAudioDecoder::CreateDataPipe() { | |
195 // Allocate DataPipe size based on audio content. 100kb should suffice. | |
196 MojoCreateDataPipeOptions options; | |
197 options.struct_size = sizeof(MojoCreateDataPipeOptions); | |
198 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
199 options.element_num_bytes = 1; | |
200 options.capacity_num_bytes = 100 * 1024; | |
xhwang
2016/03/19 04:57:25
We use 512k for audio in mojo_demuxer_stream: http
Tima Vaisburd
2016/03/19 22:04:46
We can calculate from the configuration if we know
xhwang
2016/03/20 16:15:57
Why 48k is the limit and why 20ms? We'll have only
Tima Vaisburd
2016/03/21 19:08:26
Used 512k and added TODO to evaluate a smaller siz
| |
201 | |
202 mojo::DataPipe write_pipe(options); | |
203 | |
204 // Keep producer end. | |
205 producer_handle_ = std::move(write_pipe.producer_handle); | |
206 | |
207 // Pass consumer end to |remote_decoder_|. | |
208 remote_decoder_->SetDataSource(std::move(write_pipe.consumer_handle)); | |
209 } | |
210 | |
211 interfaces::DecoderBufferPtr MojoAudioDecoder::TransferDecoderBuffer( | |
212 const scoped_refptr<DecoderBuffer>& media_buffer) { | |
213 interfaces::DecoderBufferPtr buffer = | |
214 interfaces::DecoderBuffer::From(media_buffer); | |
215 if (media_buffer->end_of_stream()) | |
216 return buffer; | |
217 | |
218 // Serialize the data section of the DecoderBuffer into our pipe. | |
219 uint32_t num_bytes = base::checked_cast<uint32_t>(media_buffer->data_size()); | |
220 DCHECK_GT(num_bytes, 0u); | |
221 CHECK_EQ(WriteDataRaw(producer_handle_.get(), media_buffer->data(), | |
222 &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE), | |
223 MOJO_RESULT_OK); | |
224 CHECK_EQ(num_bytes, static_cast<uint32_t>(media_buffer->data_size())); | |
225 return buffer; | |
226 } | |
227 | |
193 } // namespace media | 228 } // namespace media |
OLD | NEW |