OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/video_decoder_selector.h" | 5 #include "media/filters/video_decoder_selector.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
11 #include "media/base/bind_to_loop.h" | 11 #include "media/base/bind_to_loop.h" |
12 #include "media/base/demuxer_stream.h" | 12 #include "media/base/demuxer_stream.h" |
13 #include "media/base/pipeline.h" | 13 #include "media/base/pipeline.h" |
14 #include "media/base/video_decoder_config.h" | 14 #include "media/base/video_decoder_config.h" |
15 #include "media/filters/decrypting_demuxer_stream.h" | 15 #include "media/filters/decrypting_demuxer_stream.h" |
16 #include "media/filters/decrypting_video_decoder.h" | 16 #include "media/filters/decrypting_video_decoder.h" |
17 | 17 |
18 namespace media { | 18 namespace media { |
19 | 19 |
20 VideoDecoderSelector::VideoDecoderSelector( | 20 VideoDecoderSelector::VideoDecoderSelector( |
21 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 21 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
22 const VideoDecoderList& decoders, | 22 ScopedVector<VideoDecoder> decoders, |
23 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 23 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
24 : message_loop_(message_loop), | 24 : message_loop_(message_loop), |
25 decoders_(decoders), | 25 decoders_(decoders.Pass()), |
26 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 26 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
27 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 27 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
28 } | 28 } |
29 | 29 |
30 VideoDecoderSelector::~VideoDecoderSelector() {} | 30 VideoDecoderSelector::~VideoDecoderSelector() {} |
31 | 31 |
32 void VideoDecoderSelector::SelectVideoDecoder( | 32 void VideoDecoderSelector::SelectVideoDecoder( |
33 const scoped_refptr<DemuxerStream>& stream, | 33 const scoped_refptr<DemuxerStream>& stream, |
34 const StatisticsCB& statistics_cb, | 34 const StatisticsCB& statistics_cb, |
35 const SelectDecoderCB& select_decoder_cb) { | 35 const SelectDecoderCB& select_decoder_cb) { |
36 DVLOG(2) << "SelectVideoDecoder()"; | 36 DVLOG(2) << "SelectVideoDecoder()"; |
37 DCHECK(message_loop_->BelongsToCurrentThread()); | 37 DCHECK(message_loop_->BelongsToCurrentThread()); |
38 DCHECK(stream); | 38 DCHECK(stream); |
39 | 39 |
40 // Make sure |select_decoder_cb| runs on a different execution stack. | 40 // Make sure |select_decoder_cb| runs on a different execution stack. |
41 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); | 41 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); |
42 | 42 |
43 const VideoDecoderConfig& config = stream->video_decoder_config(); | 43 const VideoDecoderConfig& config = stream->video_decoder_config(); |
44 if (!config.IsValidConfig()) { | 44 if (!config.IsValidConfig()) { |
45 DLOG(ERROR) << "Invalid video stream config."; | 45 DLOG(ERROR) << "Invalid video stream config."; |
46 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | 46 base::ResetAndReturn(&select_decoder_cb_).Run( |
| 47 scoped_ptr<VideoDecoder>(), NULL); |
47 return; | 48 return; |
48 } | 49 } |
49 | 50 |
50 input_stream_ = stream; | 51 input_stream_ = stream; |
51 statistics_cb_ = statistics_cb; | 52 statistics_cb_ = statistics_cb; |
52 | 53 |
53 if (!config.is_encrypted()) { | 54 if (!config.is_encrypted()) { |
54 if (decoders_.empty()) { | 55 InitializeDecoder(decoders_.begin()); |
55 DLOG(ERROR) << "No video decoder can be used to decode the input stream."; | |
56 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | |
57 return; | |
58 } | |
59 | |
60 InitializeNextDecoder(); | |
61 return; | 56 return; |
62 } | 57 } |
63 | 58 |
64 // This could happen if Encrypted Media Extension (EME) is not enabled. | 59 // This could happen if Encrypted Media Extension (EME) is not enabled. |
65 if (set_decryptor_ready_cb_.is_null()) { | 60 if (set_decryptor_ready_cb_.is_null()) { |
66 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | 61 base::ResetAndReturn(&select_decoder_cb_).Run( |
| 62 scoped_ptr<VideoDecoder>(), NULL); |
67 return; | 63 return; |
68 } | 64 } |
69 | 65 |
70 video_decoder_ = new DecryptingVideoDecoder(message_loop_, | 66 video_decoder_.reset(new DecryptingVideoDecoder( |
71 set_decryptor_ready_cb_); | 67 message_loop_, set_decryptor_ready_cb_)); |
72 | 68 |
73 video_decoder_->Initialize( | 69 video_decoder_->Initialize( |
74 input_stream_, | 70 input_stream_, |
75 BindToCurrentLoop(base::Bind( | 71 BindToCurrentLoop(base::Bind( |
76 &VideoDecoderSelector::DecryptingVideoDecoderInitDone, | 72 &VideoDecoderSelector::DecryptingVideoDecoderInitDone, |
77 weak_ptr_factory_.GetWeakPtr())), | 73 weak_ptr_factory_.GetWeakPtr())), |
78 statistics_cb_); | 74 statistics_cb_); |
79 } | 75 } |
80 | 76 |
81 void VideoDecoderSelector::DecryptingVideoDecoderInitDone( | 77 void VideoDecoderSelector::DecryptingVideoDecoderInitDone( |
82 PipelineStatus status) { | 78 PipelineStatus status) { |
83 DCHECK(message_loop_->BelongsToCurrentThread()); | 79 DCHECK(message_loop_->BelongsToCurrentThread()); |
84 | 80 |
85 if (status == PIPELINE_OK) { | 81 if (status == PIPELINE_OK) { |
86 decoders_.clear(); | 82 base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_.Pass(), NULL); |
87 base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_, NULL); | |
88 return; | 83 return; |
89 } | 84 } |
90 | 85 |
91 video_decoder_ = NULL; | |
92 | |
93 if (decoders_.empty()) { | |
94 DLOG(ERROR) << "No video decoder can be used to decode the input stream."; | |
95 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | |
96 return; | |
97 } | |
98 | |
99 decrypted_stream_ = new DecryptingDemuxerStream( | 86 decrypted_stream_ = new DecryptingDemuxerStream( |
100 message_loop_, set_decryptor_ready_cb_); | 87 message_loop_, set_decryptor_ready_cb_); |
101 | 88 |
102 decrypted_stream_->Initialize( | 89 decrypted_stream_->Initialize( |
103 input_stream_, | 90 input_stream_, |
104 BindToCurrentLoop(base::Bind( | 91 BindToCurrentLoop(base::Bind( |
105 &VideoDecoderSelector::DecryptingDemuxerStreamInitDone, | 92 &VideoDecoderSelector::DecryptingDemuxerStreamInitDone, |
106 weak_ptr_factory_.GetWeakPtr()))); | 93 weak_ptr_factory_.GetWeakPtr()))); |
107 } | 94 } |
108 | 95 |
109 void VideoDecoderSelector::DecryptingDemuxerStreamInitDone( | 96 void VideoDecoderSelector::DecryptingDemuxerStreamInitDone( |
110 PipelineStatus status) { | 97 PipelineStatus status) { |
111 DCHECK(message_loop_->BelongsToCurrentThread()); | 98 DCHECK(message_loop_->BelongsToCurrentThread()); |
112 | 99 |
113 if (status != PIPELINE_OK) { | 100 if (status != PIPELINE_OK) { |
114 decrypted_stream_ = NULL; | 101 decrypted_stream_ = NULL; |
115 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | 102 base::ResetAndReturn(&select_decoder_cb_).Run( |
| 103 scoped_ptr<VideoDecoder>(), NULL); |
116 return; | 104 return; |
117 } | 105 } |
118 | 106 |
119 DCHECK(!decrypted_stream_->video_decoder_config().is_encrypted()); | 107 DCHECK(!decrypted_stream_->video_decoder_config().is_encrypted()); |
120 input_stream_ = decrypted_stream_; | 108 input_stream_ = decrypted_stream_; |
121 InitializeNextDecoder(); | 109 InitializeDecoder(decoders_.begin()); |
122 } | 110 } |
123 | 111 |
124 void VideoDecoderSelector::InitializeNextDecoder() { | 112 void VideoDecoderSelector::InitializeDecoder( |
| 113 ScopedVector<VideoDecoder>::iterator iter) { |
125 DCHECK(message_loop_->BelongsToCurrentThread()); | 114 DCHECK(message_loop_->BelongsToCurrentThread()); |
126 DCHECK(!decoders_.empty()); | |
127 | 115 |
128 video_decoder_ = decoders_.front(); | 116 if (iter == decoders_.end()) { |
129 decoders_.pop_front(); | 117 base::ResetAndReturn(&select_decoder_cb_).Run( |
130 DCHECK(video_decoder_); | 118 scoped_ptr<VideoDecoder>(), NULL); |
131 video_decoder_->Initialize(input_stream_, | 119 return; |
132 BindToCurrentLoop(base::Bind( | 120 } |
133 &VideoDecoderSelector::DecoderInitDone, | 121 |
134 weak_ptr_factory_.GetWeakPtr())), | 122 (*iter)->Initialize( |
135 statistics_cb_); | 123 input_stream_, |
| 124 BindToCurrentLoop(base::Bind( |
| 125 &VideoDecoderSelector::DecoderInitDone, |
| 126 weak_ptr_factory_.GetWeakPtr(), |
| 127 iter)), |
| 128 statistics_cb_); |
136 } | 129 } |
137 | 130 |
138 void VideoDecoderSelector::DecoderInitDone(PipelineStatus status) { | 131 void VideoDecoderSelector::DecoderInitDone( |
| 132 ScopedVector<VideoDecoder>::iterator iter, PipelineStatus status) { |
139 DCHECK(message_loop_->BelongsToCurrentThread()); | 133 DCHECK(message_loop_->BelongsToCurrentThread()); |
140 | 134 |
141 if (status != PIPELINE_OK) { | 135 if (status != PIPELINE_OK) { |
142 if (!decoders_.empty()) | 136 InitializeDecoder(++iter); |
143 InitializeNextDecoder(); | |
144 else | |
145 base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); | |
146 return; | 137 return; |
147 } | 138 } |
148 | 139 |
149 decoders_.clear(); | 140 scoped_ptr<VideoDecoder> video_decoder(*iter); |
150 base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_, | 141 decoders_.weak_erase(iter); |
| 142 |
| 143 base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder.Pass(), |
151 decrypted_stream_); | 144 decrypted_stream_); |
152 } | 145 } |
153 | 146 |
154 } // namespace media | 147 } // namespace media |
OLD | NEW |