| 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/filters/pipeline_controller.h" | 5 #include "media/filters/pipeline_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "media/base/demuxer.h" | 8 #include "media/base/demuxer.h" |
| 9 | 9 |
| 10 namespace media { | 10 namespace media { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 state_ = State::STARTING; | 48 state_ = State::STARTING; |
| 49 | 49 |
| 50 demuxer_ = demuxer; | 50 demuxer_ = demuxer; |
| 51 is_streaming_ = is_streaming; | 51 is_streaming_ = is_streaming; |
| 52 is_static_ = is_static; | 52 is_static_ = is_static; |
| 53 pipeline_->Start(demuxer, renderer_factory_cb_.Run(), client, | 53 pipeline_->Start(demuxer, renderer_factory_cb_.Run(), client, |
| 54 base::Bind(&PipelineController::OnPipelineStatus, | 54 base::Bind(&PipelineController::OnPipelineStatus, |
| 55 weak_factory_.GetWeakPtr(), State::PLAYING)); | 55 weak_factory_.GetWeakPtr(), State::PLAYING)); |
| 56 } | 56 } |
| 57 | 57 |
| 58 void PipelineController::Seek(base::TimeDelta time, bool time_updated) { | 58 void PipelineController::Seek(StreamPosition position, bool time_updated) { |
| 59 DCHECK(thread_checker_.CalledOnValidThread()); | 59 DCHECK(thread_checker_.CalledOnValidThread()); |
| 60 | 60 |
| 61 // It would be slightly more clear to set this in Dispatch(), but we want to | 61 // It would be slightly more clear to set this in Dispatch(), but we want to |
| 62 // be sure it gets updated even if the seek is elided. | 62 // be sure it gets updated even if the seek is elided. |
| 63 if (time_updated) | 63 if (time_updated) |
| 64 pending_time_updated_ = true; | 64 pending_time_updated_ = true; |
| 65 pending_seeked_cb_ = true; | 65 pending_seeked_cb_ = true; |
| 66 | 66 |
| 67 // If we are already seeking to |time|, and the media is static, elide the | 67 // If we are already seeking to |time|, and the media is static, elide the |
| 68 // seek. | 68 // seek. |
| 69 if ((state_ == State::SEEKING || state_ == State::RESUMING) && | 69 if ((state_ == State::SEEKING || state_ == State::RESUMING) && |
| 70 seek_time_ == time && is_static_) { | 70 seek_position_ == position && is_static_) { |
| 71 pending_seek_ = false; | 71 pending_seek_ = false; |
| 72 return; | 72 return; |
| 73 } | 73 } |
| 74 | 74 |
| 75 pending_seek_time_ = time; | 75 pending_seek_position_ = position; |
| 76 pending_seek_ = true; | 76 pending_seek_ = true; |
| 77 Dispatch(); | 77 Dispatch(); |
| 78 } | 78 } |
| 79 | 79 |
| 80 // TODO(sandersd): It may be easier to use this interface if |suspended_cb_| is | 80 // TODO(sandersd): It may be easier to use this interface if |suspended_cb_| is |
| 81 // executed when Suspend() is called while already suspended. | 81 // executed when Suspend() is called while already suspended. |
| 82 void PipelineController::Suspend() { | 82 void PipelineController::Suspend() { |
| 83 DCHECK(thread_checker_.CalledOnValidThread()); | 83 DCHECK(thread_checker_.CalledOnValidThread()); |
| 84 pending_resume_ = false; | 84 pending_resume_ = false; |
| 85 if (state_ != State::SUSPENDING && state_ != State::SUSPENDED) { | 85 if (state_ != State::SUSPENDING && state_ != State::SUSPENDED) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 state_ = State::SUSPENDING; | 150 state_ = State::SUSPENDING; |
| 151 pipeline_->Suspend(base::Bind(&PipelineController::OnPipelineStatus, | 151 pipeline_->Suspend(base::Bind(&PipelineController::OnPipelineStatus, |
| 152 weak_factory_.GetWeakPtr(), | 152 weak_factory_.GetWeakPtr(), |
| 153 State::SUSPENDED)); | 153 State::SUSPENDED)); |
| 154 return; | 154 return; |
| 155 } | 155 } |
| 156 | 156 |
| 157 if (pending_resume_ && state_ == State::SUSPENDED) { | 157 if (pending_resume_ && state_ == State::SUSPENDED) { |
| 158 // If there is a pending seek, resume to that time instead... | 158 // If there is a pending seek, resume to that time instead... |
| 159 if (pending_seek_) { | 159 if (pending_seek_) { |
| 160 seek_time_ = pending_seek_time_; | 160 seek_position_ = StreamPosition::Precise(pending_seek_position_.time); |
| 161 pending_seek_ = false; | 161 pending_seek_ = false; |
| 162 } else { | 162 } else { |
| 163 seek_time_ = pipeline_->GetMediaTime(); | 163 seek_position_ = StreamPosition::Precise(pipeline_->GetMediaTime()); |
| 164 } | 164 } |
| 165 | 165 |
| 166 // ...unless the media is streaming, in which case we resume at the start | 166 // ...unless the media is streaming, in which case we resume at the start |
| 167 // because seeking doesn't work well. | 167 // because seeking doesn't work well. |
| 168 if (is_streaming_ && !seek_time_.is_zero()) { | 168 if (is_streaming_ && !seek_position_.time.is_zero()) { |
| 169 seek_time_ = base::TimeDelta(); | 169 seek_position_ = StreamPosition::Precise(base::TimeDelta()); |
| 170 | 170 |
| 171 // In this case we want to make sure that the controls get updated | 171 // In this case we want to make sure that the controls get updated |
| 172 // immediately, so we don't try to hide the seek. | 172 // immediately, so we don't try to hide the seek. |
| 173 pending_time_updated_ = true; | 173 pending_time_updated_ = true; |
| 174 } | 174 } |
| 175 | 175 |
| 176 // Tell |demuxer_| to expect our resume. | 176 // Tell |demuxer_| to expect our resume. |
| 177 DCHECK(!waiting_for_seek_); | 177 DCHECK(!waiting_for_seek_); |
| 178 waiting_for_seek_ = true; | 178 waiting_for_seek_ = true; |
| 179 demuxer_->StartWaitingForSeek(seek_time_); | 179 demuxer_->StartWaitingForSeek(seek_position_.time); |
| 180 | 180 |
| 181 pending_resume_ = false; | 181 pending_resume_ = false; |
| 182 state_ = State::RESUMING; | 182 state_ = State::RESUMING; |
| 183 pipeline_->Resume(renderer_factory_cb_.Run(), seek_time_, | 183 pipeline_->Resume(renderer_factory_cb_.Run(), seek_position_.time, |
| 184 base::Bind(&PipelineController::OnPipelineStatus, | 184 base::Bind(&PipelineController::OnPipelineStatus, |
| 185 weak_factory_.GetWeakPtr(), State::PLAYING)); | 185 weak_factory_.GetWeakPtr(), State::PLAYING)); |
| 186 return; | 186 return; |
| 187 } | 187 } |
| 188 | 188 |
| 189 // If we have pending operations, and a seek is ongoing, abort it. | 189 // If we have pending operations, and a seek is ongoing, abort it. |
| 190 if ((pending_seek_ || pending_suspend_) && waiting_for_seek_) { | 190 if ((pending_seek_ || pending_suspend_) && waiting_for_seek_) { |
| 191 // If there is no pending seek, return the current seek to pending status. | 191 // If there is no pending seek, return the current seek to pending status. |
| 192 if (!pending_seek_) { | 192 if (!pending_seek_) { |
| 193 pending_seek_time_ = seek_time_; | 193 pending_seek_position_ = seek_position_; |
| 194 pending_seek_ = true; | 194 pending_seek_ = true; |
| 195 } | 195 } |
| 196 | 196 |
| 197 // CancelPendingSeek() may be reentrant, so update state first and return | 197 // CancelPendingSeek() may be reentrant, so update state first and return |
| 198 // immediately. | 198 // immediately. |
| 199 waiting_for_seek_ = false; | 199 waiting_for_seek_ = false; |
| 200 demuxer_->CancelPendingSeek(pending_seek_time_); | 200 demuxer_->CancelPendingSeek(pending_seek_position_.time); |
| 201 return; | 201 return; |
| 202 } | 202 } |
| 203 | 203 |
| 204 // Ordinary seeking. | 204 // Ordinary seeking. |
| 205 if (pending_seek_ && state_ == State::PLAYING) { | 205 if (pending_seek_ && state_ == State::PLAYING) { |
| 206 seek_time_ = pending_seek_time_; | 206 seek_position_ = pending_seek_position_; |
| 207 | 207 |
| 208 // Tell |demuxer_| to expect our seek. | 208 // Tell |demuxer_| to expect our seek. |
| 209 DCHECK(!waiting_for_seek_); | 209 DCHECK(!waiting_for_seek_); |
| 210 waiting_for_seek_ = true; | 210 waiting_for_seek_ = true; |
| 211 demuxer_->StartWaitingForSeek(seek_time_); | 211 demuxer_->StartWaitingForSeek(seek_position_.time); |
| 212 | 212 |
| 213 pending_seek_ = false; | 213 pending_seek_ = false; |
| 214 state_ = State::SEEKING; | 214 state_ = State::SEEKING; |
| 215 pipeline_->Seek(seek_time_, | 215 pipeline_->Seek(seek_position_, |
| 216 base::Bind(&PipelineController::OnPipelineStatus, | 216 base::Bind(&PipelineController::OnPipelineStatus, |
| 217 weak_factory_.GetWeakPtr(), State::PLAYING)); | 217 weak_factory_.GetWeakPtr(), State::PLAYING)); |
| 218 return; | 218 return; |
| 219 } | 219 } |
| 220 | 220 |
| 221 // If |state_| is PLAYING and we didn't trigger an operation above then we | 221 // If |state_| is PLAYING and we didn't trigger an operation above then we |
| 222 // are in a stable state. If there is a seeked callback pending, emit it. | 222 // are in a stable state. If there is a seeked callback pending, emit it. |
| 223 if (state_ == State::PLAYING) { | 223 if (state_ == State::PLAYING) { |
| 224 if (pending_seeked_cb_) { | 224 if (pending_seeked_cb_) { |
| 225 // |seeked_cb_| may be reentrant, so update state first and return | 225 // |seeked_cb_| may be reentrant, so update state first and return |
| 226 // immediately. | 226 // immediately. |
| 227 pending_seeked_cb_ = false; | 227 pending_seeked_cb_ = false; |
| 228 bool was_pending_time_updated = pending_time_updated_; | 228 bool was_pending_time_updated = pending_time_updated_; |
| 229 pending_time_updated_ = false; | 229 pending_time_updated_ = false; |
| 230 seeked_cb_.Run(was_pending_time_updated); | 230 seeked_cb_.Run(was_pending_time_updated); |
| 231 return; | 231 return; |
| 232 } | 232 } |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 } // namespace media | 236 } // namespace media |
| OLD | NEW |