Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: media/filters/video_renderer_base.cc

Issue 160620: Fix video sync error when framerate or playback rate is low... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | media/filters/video_renderer_base_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | media/filters/video_renderer_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698