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" | |
9 #include "base/callback_helpers.h" | |
8 #include "base/location.h" | 10 #include "base/location.h" |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
11 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
14 #include "media/base/cdm_context.h" | |
15 #include "media/mojo/common/media_type_converters.h" | |
12 | 16 |
13 namespace media { | 17 namespace media { |
14 | 18 |
15 MojoAudioDecoder::MojoAudioDecoder( | 19 MojoAudioDecoder::MojoAudioDecoder( |
16 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 20 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
17 interfaces::AudioDecoderPtr remote_decoder) | 21 interfaces::AudioDecoderPtr remote_decoder) |
18 : task_runner_(task_runner), remote_decoder_(std::move(remote_decoder)) { | 22 : task_runner_(task_runner), |
23 remote_decoder_(std::move(remote_decoder)), | |
24 binding_(this), | |
25 has_connection_error_(false), | |
26 needs_bitstream_conversion_(false) { | |
19 DVLOG(1) << __FUNCTION__; | 27 DVLOG(1) << __FUNCTION__; |
20 } | 28 } |
21 | 29 |
22 MojoAudioDecoder::~MojoAudioDecoder() { | 30 MojoAudioDecoder::~MojoAudioDecoder() { |
23 DVLOG(1) << __FUNCTION__; | 31 DVLOG(1) << __FUNCTION__; |
24 } | 32 } |
25 | 33 |
26 std::string MojoAudioDecoder::GetDisplayName() const { | 34 std::string MojoAudioDecoder::GetDisplayName() const { |
27 return "MojoAudioDecoder"; | 35 return "MojoAudioDecoder"; |
28 } | 36 } |
29 | 37 |
30 void MojoAudioDecoder::Initialize(const AudioDecoderConfig& config, | 38 void MojoAudioDecoder::Initialize(const AudioDecoderConfig& config, |
31 CdmContext* cdm_context, | 39 CdmContext* cdm_context, |
32 const InitCB& init_cb, | 40 const InitCB& init_cb, |
33 const OutputCB& output_cb) { | 41 const OutputCB& output_cb) { |
34 DVLOG(1) << __FUNCTION__; | 42 DVLOG(1) << __FUNCTION__; |
35 DCHECK(task_runner_->BelongsToCurrentThread()); | 43 DCHECK(task_runner_->BelongsToCurrentThread()); |
36 | 44 |
37 NOTIMPLEMENTED(); | 45 // Fail immediately if the stream is encrypted but |cdm_context| is invalid. |
46 int cdm_id = (config.is_encrypted() && cdm_context) | |
47 ? cdm_context->GetCdmId() | |
48 : CdmContext::kInvalidCdmId; | |
38 | 49 |
39 // Fail initialization while not implemented. | 50 if (config.is_encrypted() && CdmContext::kInvalidCdmId == cdm_id) { |
40 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); | 51 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); |
52 return; | |
53 } | |
54 | |
55 // If connection error has happened, fail immediately. | |
56 if (remote_decoder_.encountered_error()) { | |
57 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); | |
58 return; | |
59 } | |
60 | |
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; | |
68 | |
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. | |
71 remote_decoder_->Initialize( | |
72 binding_.CreateInterfacePtrAndBind(), | |
73 interfaces::AudioDecoderConfig::From(config), cdm_id, | |
74 base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); | |
41 } | 75 } |
42 | 76 |
43 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 77 void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
44 const DecodeCB& decode_cb) { | 78 const DecodeCB& decode_cb) { |
45 DVLOG(3) << __FUNCTION__; | 79 DVLOG(3) << __FUNCTION__; |
46 DCHECK(task_runner_->BelongsToCurrentThread()); | 80 DCHECK(task_runner_->BelongsToCurrentThread()); |
47 | 81 |
48 NOTIMPLEMENTED(); | 82 if (has_connection_error_) { |
83 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); | |
84 return; | |
85 } | |
49 | 86 |
50 // Actually we can't decode anything. | 87 DCHECK(decode_cb_.is_null()); |
51 task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); | 88 decode_cb_ = decode_cb; |
89 | |
90 remote_decoder_->Decode( | |
91 interfaces::DecoderBuffer::From(buffer), | |
92 base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); | |
52 } | 93 } |
53 | 94 |
54 void MojoAudioDecoder::Reset(const base::Closure& closure) { | 95 void MojoAudioDecoder::Reset(const base::Closure& closure) { |
55 DVLOG(2) << __FUNCTION__; | 96 DVLOG(2) << __FUNCTION__; |
56 DCHECK(task_runner_->BelongsToCurrentThread()); | 97 DCHECK(task_runner_->BelongsToCurrentThread()); |
57 | 98 |
58 NOTIMPLEMENTED(); | 99 if (has_connection_error_) { |
100 if (!decode_cb_.is_null()) { | |
101 task_runner_->PostTask( | |
102 FROM_HERE, | |
103 base::Bind(base::ResetAndReturn(&decode_cb_), kDecodeError)); | |
104 } | |
105 | |
106 task_runner_->PostTask(FROM_HERE, closure); | |
107 return; | |
108 } | |
109 | |
110 DCHECK(reset_cb_.is_null()); | |
111 reset_cb_ = closure; | |
112 remote_decoder_->Reset( | |
113 base::Bind(&MojoAudioDecoder::OnResetDone, base::Unretained(this))); | |
59 } | 114 } |
60 | 115 |
61 bool MojoAudioDecoder::NeedsBitstreamConversion() const { | 116 bool MojoAudioDecoder::NeedsBitstreamConversion() const { |
62 DVLOG(1) << __FUNCTION__; | 117 DVLOG(1) << __FUNCTION__; |
63 DCHECK(task_runner_->BelongsToCurrentThread()); | 118 DCHECK(task_runner_->BelongsToCurrentThread()); |
64 | 119 |
120 return needs_bitstream_conversion_; | |
121 } | |
122 | |
123 void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { | |
124 DVLOG(1) << __FUNCTION__; | |
125 DCHECK(task_runner_->BelongsToCurrentThread()); | |
126 | |
65 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
66 return false; | 128 } |
129 | |
130 void MojoAudioDecoder::OnConnectionError() { | |
131 DVLOG(1) << __FUNCTION__; | |
132 DCHECK(task_runner_->BelongsToCurrentThread()); | |
133 | |
134 has_connection_error_ = true; | |
135 | |
136 if (!init_cb_.is_null()) { | |
137 base::ResetAndReturn(&init_cb_).Run(false); | |
138 return; | |
139 } | |
140 | |
141 if (!decode_cb_.is_null()) | |
142 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | |
143 if (!reset_cb_.is_null()) | |
144 base::ResetAndReturn(&reset_cb_).Run(); | |
145 } | |
146 | |
147 void MojoAudioDecoder::OnInitialized(bool status, | |
148 bool needs_bitstream_conversion) { | |
149 DVLOG(1) << __FUNCTION__ << ": status:" << status; | |
150 DCHECK(task_runner_->BelongsToCurrentThread()); | |
151 | |
152 needs_bitstream_conversion_ = needs_bitstream_conversion; | |
153 | |
154 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); | |
155 } | |
156 | |
157 static media::AudioDecoder::Status ConvertDecodeStatus( | |
158 interfaces::AudioDecoder::DecodeStatus status) { | |
159 switch (status) { | |
160 case interfaces::AudioDecoder::DecodeStatus::OK: | |
161 return media::AudioDecoder::kOk; | |
162 case interfaces::AudioDecoder::DecodeStatus::ABORTED: | |
163 return media::AudioDecoder::kAborted; | |
164 case interfaces::AudioDecoder::DecodeStatus::DECODE_ERROR: | |
165 return media::AudioDecoder::kDecodeError; | |
166 } | |
167 NOTREACHED(); | |
168 return media::AudioDecoder::kDecodeError; | |
169 } | |
170 | |
171 void MojoAudioDecoder::OnDecodeStatus( | |
172 interfaces::AudioDecoder::DecodeStatus status) { | |
173 DVLOG(1) << __FUNCTION__ << ": status:" << status; | |
174 DCHECK(task_runner_->BelongsToCurrentThread()); | |
175 | |
176 DCHECK(!decode_cb_.is_null()); | |
177 base::ResetAndReturn(&decode_cb_).Run(ConvertDecodeStatus(status)); | |
178 } | |
179 | |
180 void MojoAudioDecoder::OnResetDone() { | |
181 DVLOG(1) << __FUNCTION__; | |
182 DCHECK(task_runner_->BelongsToCurrentThread()); | |
183 | |
184 DCHECK(!reset_cb_.is_null()); | |
xhwang
2016/03/18 19:17:17
DCHECK that there's no decode callback pending.
Tima Vaisburd
2016/03/18 19:35:03
Done.
| |
185 base::ResetAndReturn(&reset_cb_).Run(); | |
67 } | 186 } |
68 | 187 |
69 } // namespace media | 188 } // namespace media |
OLD | NEW |