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

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

Issue 165163: Merge 21882 - Implemented a proper clock for audio/video synchronization.... (Closed) Base URL: svn://chrome-svn/chrome/branches/195/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 | « media/base/pipeline_impl.cc ('k') | media/media.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Modified: svn:mergeinfo
Merged /trunk/src/media/filters/video_renderer_base.cc:r21882
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 // Sleeping for negative amounts actually hangs your thread on Windows! 24 // This equates to ~16.67 fps, which is just slow enough to be tolerable when
25 static const int64 kMinSleepMilliseconds = 0; 25 // our video renderer is ahead of the audio playback.
26 26 //
27 // This equates to ~13.33 fps, which is just under the typical 15 fps that 27 // A higher value will be a slower frame rate, which looks worse but allows the
28 // lower quality cameras or shooting modes usually use for video encoding. 28 // audio renderer to catch up faster. A lower value will be a smoother frame
29 static const int64 kMaxSleepMilliseconds = 75; 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 33
31 VideoRendererBase::VideoRendererBase() 34 VideoRendererBase::VideoRendererBase()
32 : width_(0), 35 : width_(0),
33 height_(0), 36 height_(0),
34 frame_available_(&lock_), 37 frame_available_(&lock_),
35 state_(kUninitialized), 38 state_(kUninitialized),
36 thread_(NULL), 39 thread_(NULL),
37 pending_reads_(0), 40 pending_reads_(0),
38 playback_rate_(0) { 41 playback_rate_(0) {
39 } 42 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 continue; 232 continue;
230 } 233 }
231 234
232 // Update our current frame and attempt to grab the next frame. 235 // Update our current frame and attempt to grab the next frame.
233 current_frame_ = frames_.front(); 236 current_frame_ = frames_.front();
234 if (frames_.size() >= 2) { 237 if (frames_.size() >= 2) {
235 next_frame = frames_[1]; 238 next_frame = frames_[1];
236 } 239 }
237 } 240 }
238 241
242 // Calculate our sleep duration.
243 base::TimeDelta sleep = CalculateSleepDuration(next_frame, playback_rate);
244 int sleep_ms = static_cast<int>(sleep.InMilliseconds());
245
246 // If we're too far behind to catch up, simply drop the frame.
247 //
248 // This has the effect of potentially dropping a few frames when playback
249 // resumes after being paused. The alternative (sleeping for 0 milliseconds
250 // and trying to catch up) looks worse.
251 if (sleep_ms < 0)
252 continue;
253
254 // To be safe, limit our sleep duration.
255 // TODO(scherkus): handle seeking gracefully.. right now we tend to hit
256 // kMaxSleepMilliseconds a lot when we seek backwards.
257 if (sleep_ms > kMaxSleepMilliseconds)
258 sleep_ms = kMaxSleepMilliseconds;
259
239 // Notify subclass that |current_frame_| has been updated. 260 // Notify subclass that |current_frame_| has been updated.
240 OnFrameAvailable(); 261 OnFrameAvailable();
241 262
242 // Calculate our sleep duration.
243 base::TimeDelta sleep = CalculateSleepDuration(next_frame, playback_rate);
244
245 // To be safe, limit our sleep duration.
246 // TODO(scherkus): handle seeking gracefully.. right now a seek backwards
247 // will hit kMinSleepMilliseconds whereas a seek forward will hit
248 // kMaxSleepMilliseconds.
249 int sleep_ms = static_cast<int>(sleep.InMilliseconds());
250 if (sleep_ms < kMinSleepMilliseconds)
251 sleep_ms = kMinSleepMilliseconds;
252 else if (sleep_ms > kMaxSleepMilliseconds)
253 sleep_ms = kMaxSleepMilliseconds;
254
255 PlatformThread::Sleep(sleep_ms); 263 PlatformThread::Sleep(sleep_ms);
256 } 264 }
257 } 265 }
258 266
259 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { 267 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) {
260 AutoLock auto_lock(lock_); 268 AutoLock auto_lock(lock_);
261 // We should have initialized and have the current frame. 269 // We should have initialized and have the current frame.
262 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying); 270 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying);
263 DCHECK(current_frame_); 271 DCHECK(current_frame_);
264 *frame_out = current_frame_; 272 *frame_out = current_frame_;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 surface.data[VideoSurface::kVPlane] 385 surface.data[VideoSurface::kVPlane]
378 += surface.strides[VideoSurface::kVPlane]; 386 += surface.strides[VideoSurface::kVPlane];
379 } 387 }
380 frame->Unlock(); 388 frame->Unlock();
381 389
382 // Success! 390 // Success!
383 *frame_out = frame; 391 *frame_out = frame;
384 } 392 }
385 393
386 } // namespace media 394 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline_impl.cc ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698