| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/buffers.h" | 5 #include "media/base/buffers.h" |
| 6 #include "media/base/filter_host.h" | 6 #include "media/base/filter_host.h" |
| 7 #include "media/base/video_frame_impl.h" | 7 #include "media/base/video_frame_impl.h" |
| 8 #include "media/filters/video_renderer_base.h" | 8 #include "media/filters/video_renderer_base.h" |
| 9 | 9 |
| 10 namespace media { | 10 namespace media { |
| 11 | 11 |
| 12 // Limit our read ahead to three frames. One frame is typically in flux at all | 12 // Limit our read ahead to three frames. One frame is typically in flux at all |
| 13 // times, as in frame n is discarded at the top of ThreadMain() while frame | 13 // times, as in frame n is discarded at the top of ThreadMain() while frame |
| 14 // (n + kMaxFrames) is being asynchronously fetched. The remaining two frames | 14 // (n + kMaxFrames) is being asynchronously fetched. The remaining two frames |
| 15 // allow us to advance the current frame as well as read the timestamp of the | 15 // allow us to advance the current frame as well as read the timestamp of the |
| 16 // following frame for more accurate timing. | 16 // following frame for more accurate timing. |
| 17 // | 17 // |
| 18 // Increasing this number beyond 3 simply creates a larger buffer to work with | 18 // Increasing this number beyond 3 simply creates a larger buffer to work with |
| 19 // at the expense of memory (~0.5MB and ~1.3MB per frame for 480p and 720p | 19 // at the expense of memory (~0.5MB and ~1.3MB per frame for 480p and 720p |
| 20 // resolutions, respectively). This can help on lower-end systems if there are | 20 // resolutions, respectively). This can help on lower-end systems if there are |
| 21 // difficult sections in the movie and decoding slows down. | 21 // difficult sections in the movie and decoding slows down. |
| 22 static const size_t kMaxFrames = 3; | 22 static const size_t kMaxFrames = 3; |
| 23 | 23 |
| 24 // This equates to ~16.67 fps, which is just slow enough to be tolerable when | 24 // This equates to ~16.67 fps, which is just slow enough to be tolerable when |
| 25 // our video renderer is ahead of the audio playback. | 25 // our video renderer is ahead of the audio playback. |
| 26 // | 26 // |
| 27 // A higher value will be a slower frame rate, which looks worse but allows the | 27 // A higher value will be a slower frame rate, which looks worse but allows the |
| 28 // audio renderer to catch up faster. A lower value will be a smoother frame | 28 // audio renderer to catch up faster. A lower value will be a smoother frame |
| 29 // rate, but results in the video being out of sync for longer. | 29 // rate, but results in the video being out of sync for longer. |
| 30 // | |
| 31 // TODO(scherkus): what if the native frame rate is 15 or 10 fps? | |
| 32 static const int64 kMaxSleepMilliseconds = 60; | 30 static const int64 kMaxSleepMilliseconds = 60; |
| 33 | 31 |
| 32 // The number of milliseconds to idle when we do not have anything to do. |
| 33 // Nothing special about the value, other than we're being more OS-friendly |
| 34 // than sleeping for 1 millisecond. |
| 35 static const int kIdleMilliseconds = 10; |
| 36 |
| 34 VideoRendererBase::VideoRendererBase() | 37 VideoRendererBase::VideoRendererBase() |
| 35 : width_(0), | 38 : width_(0), |
| 36 height_(0), | 39 height_(0), |
| 37 frame_available_(&lock_), | 40 frame_available_(&lock_), |
| 38 state_(kUninitialized), | 41 state_(kUninitialized), |
| 39 thread_(NULL), | 42 thread_(NULL), |
| 40 pending_reads_(0), | 43 pending_reads_(0), |
| 41 playback_rate_(0) { | 44 playback_rate_(0) { |
| 42 } | 45 } |
| 43 | 46 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 float playback_rate; | 189 float playback_rate; |
| 187 { | 190 { |
| 188 AutoLock auto_lock(lock_); | 191 AutoLock auto_lock(lock_); |
| 189 state = state_; | 192 state = state_; |
| 190 playback_rate = playback_rate_; | 193 playback_rate = playback_rate_; |
| 191 } | 194 } |
| 192 if (state == kStopped) { | 195 if (state == kStopped) { |
| 193 return; | 196 return; |
| 194 } | 197 } |
| 195 | 198 |
| 196 // Sleep for 10 milliseconds while paused. Nothing special about the value, | 199 // Sleep while paused or seeking. |
| 197 // other than we're being more OS-friendly than sleeping for 1 millisecond. | |
| 198 if (state == kPaused || state == kSeeking || playback_rate == 0) { | 200 if (state == kPaused || state == kSeeking || playback_rate == 0) { |
| 199 PlatformThread::Sleep(10); | 201 PlatformThread::Sleep(kIdleMilliseconds); |
| 200 continue; | 202 continue; |
| 201 } | 203 } |
| 202 | 204 |
| 203 // Advance |current_frame_| and try to determine |next_frame|. Note that | 205 // Advance |current_frame_| and try to determine |next_frame|. Note that |
| 204 // this loop executes our "playing" logic. | 206 // this loop executes our "playing" logic. |
| 205 DCHECK_EQ(kPlaying, state); | 207 DCHECK_EQ(kPlaying, state); |
| 206 scoped_refptr<VideoFrame> next_frame; | 208 scoped_refptr<VideoFrame> next_frame; |
| 207 { | 209 { |
| 208 AutoLock auto_lock(lock_); | 210 AutoLock auto_lock(lock_); |
| 209 // Check the actual state to see if we're trying to stop playing. | 211 // Check the actual state to see if we're trying to stop playing. |
| 210 if (state_ != kPlaying) { | 212 if (state_ != kPlaying) { |
| 211 continue; | 213 continue; |
| 212 } | 214 } |
| 213 | 215 |
| 216 // Idle if the next frame is too far ahead. |
| 217 base::TimeDelta diff = current_frame_->GetTimestamp() - host()->GetTime(); |
| 218 if (diff.InMilliseconds() > kIdleMilliseconds) { |
| 219 PlatformThread::Sleep(kIdleMilliseconds); |
| 220 continue; |
| 221 } |
| 222 |
| 214 // Otherwise we're playing, so advance the frame and keep reading from the | 223 // Otherwise we're playing, so advance the frame and keep reading from the |
| 215 // decoder. |frames_| might be empty if we seeked to the very end of the | 224 // decoder. |frames_| might be empty if we seeked to the very end of the |
| 216 // media where no frames were available. | 225 // media where no frames were available. |
| 217 if (!frames_.empty()) { | 226 if (!frames_.empty()) { |
| 218 DCHECK_EQ(current_frame_, frames_.front()); | 227 DCHECK_EQ(current_frame_, frames_.front()); |
| 219 frames_.pop_front(); | 228 frames_.pop_front(); |
| 220 ScheduleRead_Locked(); | 229 ScheduleRead_Locked(); |
| 221 } | 230 } |
| 222 | 231 |
| 223 // While playing, we'll wait until a new frame arrives before updating | 232 // While playing, we'll wait until a new frame arrives before updating |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 surface.data[VideoSurface::kVPlane] | 394 surface.data[VideoSurface::kVPlane] |
| 386 += surface.strides[VideoSurface::kVPlane]; | 395 += surface.strides[VideoSurface::kVPlane]; |
| 387 } | 396 } |
| 388 frame->Unlock(); | 397 frame->Unlock(); |
| 389 | 398 |
| 390 // Success! | 399 // Success! |
| 391 *frame_out = frame; | 400 *frame_out = frame; |
| 392 } | 401 } |
| 393 | 402 |
| 394 } // namespace media | 403 } // namespace media |
| OLD | NEW |