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

Side by Side Diff: media/base/android/media_codec_video_decoder.cc

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Moved pending buffer to Java side, preroll after decoder creation and Release() Created 5 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/base/android/media_codec_video_decoder.h" 5 #include "media/base/android/media_codec_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "media/base/android/media_codec_bridge.h" 9 #include "media/base/android/media_codec_bridge.h"
10 #include "media/base/buffers.h" 10 #include "media/base/buffers.h"
11 #include "media/base/demuxer_stream.h" 11 #include "media/base/demuxer_stream.h"
12 12
13 namespace media { 13 namespace media {
14 14
15 namespace { 15 namespace {
16 const int kDelayForStandAloneEOS = 2; // milliseconds 16 const int kDelayForStandAloneEOS = 2; // milliseconds
17 } 17 }
18 18
19 MediaCodecVideoDecoder::MediaCodecVideoDecoder( 19 MediaCodecVideoDecoder::MediaCodecVideoDecoder(
20 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 20 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
21 const base::Closure& request_data_cb, 21 const base::Closure& request_data_cb,
22 const base::Closure& starvation_cb, 22 const base::Closure& starvation_cb,
23 const base::Closure& preroll_done_cb,
23 const base::Closure& stop_done_cb, 24 const base::Closure& stop_done_cb,
24 const base::Closure& error_cb, 25 const base::Closure& error_cb,
25 const SetTimeCallback& update_current_time_cb, 26 const SetTimeCallback& update_current_time_cb,
26 const VideoSizeChangedCallback& video_size_changed_cb, 27 const VideoSizeChangedCallback& video_size_changed_cb,
27 const base::Closure& codec_created_cb) 28 const base::Closure& codec_created_cb)
28 : MediaCodecDecoder(media_task_runner, 29 : MediaCodecDecoder(media_task_runner,
29 request_data_cb, 30 request_data_cb,
30 starvation_cb, 31 starvation_cb,
32 preroll_done_cb,
31 stop_done_cb, 33 stop_done_cb,
32 error_cb, 34 error_cb,
33 "VideoDecoder"), 35 "VideoDecoder"),
34 update_current_time_cb_(update_current_time_cb), 36 update_current_time_cb_(update_current_time_cb),
35 video_size_changed_cb_(video_size_changed_cb), 37 video_size_changed_cb_(video_size_changed_cb),
36 codec_created_cb_(codec_created_cb) { 38 codec_created_cb_(codec_created_cb) {
37 } 39 }
38 40
39 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() { 41 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
40 DVLOG(1) << "VideoDecoder::~VideoDecoder()"; 42 DVLOG(1) << "VideoDecoder::~VideoDecoder()";
(...skipping 24 matching lines...) Expand all
65 } 67 }
66 } 68 }
67 69
68 void MediaCodecVideoDecoder::ReleaseDecoderResources() { 70 void MediaCodecVideoDecoder::ReleaseDecoderResources() {
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); 71 DCHECK(media_task_runner_->BelongsToCurrentThread());
70 72
71 DVLOG(1) << class_name() << "::" << __FUNCTION__; 73 DVLOG(1) << class_name() << "::" << __FUNCTION__;
72 74
73 MediaCodecDecoder::ReleaseDecoderResources(); 75 MediaCodecDecoder::ReleaseDecoderResources();
74 surface_ = gfx::ScopedJavaSurface(); 76 surface_ = gfx::ScopedJavaSurface();
77 }
78
79 void MediaCodecVideoDecoder::ReleaseMediaCodec() {
80 DCHECK(media_task_runner_->BelongsToCurrentThread());
81
82 MediaCodecDecoder::ReleaseMediaCodec();
75 delayed_buffers_.clear(); 83 delayed_buffers_.clear();
76 } 84 }
77 85
78 void MediaCodecVideoDecoder::SetVideoSurface(gfx::ScopedJavaSurface surface) { 86 void MediaCodecVideoDecoder::SetVideoSurface(gfx::ScopedJavaSurface surface) {
79 DCHECK(media_task_runner_->BelongsToCurrentThread()); 87 DCHECK(media_task_runner_->BelongsToCurrentThread());
80 88
81 DVLOG(1) << class_name() << "::" << __FUNCTION__ 89 DVLOG(1) << class_name() << "::" << __FUNCTION__
82 << (surface.IsEmpty() ? " empty" : " non-empty"); 90 << (surface.IsEmpty() ? " empty" : " non-empty");
83 91
84 surface_ = surface.Pass(); 92 surface_ = surface.Pass();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 return kConfigFailure; 160 return kConfigFailure;
153 } 161 }
154 162
155 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded"; 163 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded";
156 164
157 media_task_runner_->PostTask(FROM_HERE, codec_created_cb_); 165 media_task_runner_->PostTask(FROM_HERE, codec_created_cb_);
158 166
159 return kConfigOk; 167 return kConfigOk;
160 } 168 }
161 169
162 void MediaCodecVideoDecoder::SynchronizePTSWithTime( 170 void MediaCodecVideoDecoder::AssociateCurrentTimeWithPTS(base::TimeDelta pts) {
163 base::TimeDelta current_time) {
164 DCHECK(media_task_runner_->BelongsToCurrentThread()); 171 DCHECK(media_task_runner_->BelongsToCurrentThread());
165 172
166 start_time_ticks_ = base::TimeTicks::Now(); 173 start_time_ticks_ = base::TimeTicks::Now();
167 start_pts_ = current_time; 174 start_pts_ = pts;
168 last_seen_pts_ = current_time; 175 last_seen_pts_ = pts;
176 }
177
178 void MediaCodecVideoDecoder::DissociatePTSFromTime() {
179 DCHECK(media_task_runner_->BelongsToCurrentThread());
180
181 start_pts_ = last_seen_pts_ = kNoTimestamp();
169 } 182 }
170 183
171 void MediaCodecVideoDecoder::OnOutputFormatChanged() { 184 void MediaCodecVideoDecoder::OnOutputFormatChanged() {
172 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 185 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
173 186
174 gfx::Size prev_size = video_size_; 187 gfx::Size prev_size = video_size_;
175 188
176 // See b/18224769. The values reported from MediaCodecBridge::GetOutputFormat 189 // See b/18224769. The values reported from MediaCodecBridge::GetOutputFormat
177 // correspond to the actual video frame size, but this is not necessarily the 190 // correspond to the actual video frame size, but this is not necessarily the
178 // size that should be output. 191 // size that should be output.
179 video_size_ = configs_.video_size; 192 video_size_ = configs_.video_size;
180 if (video_size_ != prev_size) { 193 if (video_size_ != prev_size) {
181 media_task_runner_->PostTask( 194 media_task_runner_->PostTask(
182 FROM_HERE, base::Bind(video_size_changed_cb_, video_size_)); 195 FROM_HERE, base::Bind(video_size_changed_cb_, video_size_));
183 } 196 }
184 } 197 }
185 198
186 void MediaCodecVideoDecoder::Render(int buffer_index, 199 void MediaCodecVideoDecoder::Render(int buffer_index,
187 size_t size, 200 size_t size,
188 bool render_output, 201 RenderMode render_mode,
189 base::TimeDelta pts, 202 base::TimeDelta pts,
190 bool eos_encountered) { 203 bool eos_encountered) {
191 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 204 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
192 205
193 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts 206 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
194 << " index:" << buffer_index << " size:" << size 207 << " index:" << buffer_index << " size:" << size
195 << (eos_encountered ? " EOS" : ""); 208 << (eos_encountered ? " EOS" : "");
196 209
197 // Normally EOS comes as a separate access unit that does not have data, 210 // Normally EOS comes as a separate access unit that does not have data,
198 // the corresponding |size| will be 0. 211 // the corresponding |size| will be 0.
199 if (!size && eos_encountered) { 212 if (!size && eos_encountered) {
200 // Stand-alone EOS 213 // Stand-alone EOS
201 // Discard the PTS that comes with it and ensure it is released last. 214 // Discard the PTS that comes with it and ensure it is released last.
202 pts = last_seen_pts_ + 215 pts = last_seen_pts_ +
203 base::TimeDelta::FromMilliseconds(kDelayForStandAloneEOS); 216 base::TimeDelta::FromMilliseconds(kDelayForStandAloneEOS);
204 } else { 217 } else {
205 // Keep track of last seen PTS 218 // Keep track of last seen PTS
206 last_seen_pts_ = pts; 219 last_seen_pts_ = pts;
207 } 220 }
208 221
209 if (!render_output) { 222 // For video we simplify the preroll operation and render the first frame
223 // after preroll during the preroll phase, i.e. without waiting for audio
224 // stream to finish prerolling.
225 const bool render_output = (render_mode != kRenderSkip);
226
227 if (!render_output || start_pts_ == kNoTimestamp()) {
210 ReleaseOutputBuffer(buffer_index, pts, size, false, eos_encountered); 228 ReleaseOutputBuffer(buffer_index, pts, size, false, eos_encountered);
211 return; 229 return;
212 } 230 }
213 231
214 base::TimeDelta time_to_render = 232 base::TimeDelta time_to_render =
215 pts - (base::TimeTicks::Now() - start_time_ticks_ + start_pts_); 233 pts - (base::TimeTicks::Now() - start_time_ticks_ + start_pts_);
216 234
217 if (time_to_render < base::TimeDelta()) { 235 if (time_to_render < base::TimeDelta()) {
218 // Skip late frames 236 // Skip late frames
219 ReleaseOutputBuffer(buffer_index, pts, size, false, eos_encountered); 237 ReleaseOutputBuffer(buffer_index, pts, size, false, eos_encountered);
220 return; 238 return;
221 } 239 }
222 240
223 delayed_buffers_.insert(buffer_index); 241 delayed_buffers_.insert(buffer_index);
224 242
225 bool do_render = size > 0; 243 bool do_render = size > 0;
226 decoder_thread_.task_runner()->PostDelayedTask( 244 decoder_thread_.task_runner()->PostDelayedTask(
227 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::ReleaseOutputBuffer, 245 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::ReleaseOutputBuffer,
228 base::Unretained(this), buffer_index, pts, 246 base::Unretained(this), buffer_index, pts,
229 size, do_render, eos_encountered), 247 size, do_render, eos_encountered),
230 time_to_render); 248 time_to_render);
231 } 249 }
232 250
233 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const { 251 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const {
234 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 252 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
235 253
236 return delayed_buffers_.size(); 254 return delayed_buffers_.size();
237 } 255 }
238 256
239 void MediaCodecVideoDecoder::ClearDelayedBuffers(bool release) { 257 void MediaCodecVideoDecoder::ReleaseDelayedBuffers() {
240 // Media thread 258 // Media thread
241 // Called when there is no decoder thread 259 // Called when there is no decoder thread
242 if (release) { 260 for (int index : delayed_buffers_)
243 for (int index : delayed_buffers_) 261 media_codec_bridge_->ReleaseOutputBuffer(index, false);
244 media_codec_bridge_->ReleaseOutputBuffer(index, false);
245 }
246 262
247 delayed_buffers_.clear(); 263 delayed_buffers_.clear();
248 } 264 }
249 265
250 #ifndef NDEBUG 266 #ifndef NDEBUG
251 void MediaCodecVideoDecoder::VerifyUnitIsKeyFrame( 267 void MediaCodecVideoDecoder::VerifyUnitIsKeyFrame(
252 const AccessUnit* unit) const { 268 const AccessUnit* unit) const {
253 // The first video frame in a sequence must be a key frame or stand-alone EOS. 269 // The first video frame in a sequence must be a key frame or stand-alone EOS.
254 DCHECK(unit); 270 DCHECK(unit);
255 bool stand_alone_eos = unit->is_end_of_stream && unit->data.empty(); 271 bool stand_alone_eos = unit->is_end_of_stream && unit->data.empty();
(...skipping 18 matching lines...) Expand all
274 290
275 // |update_current_time_cb_| might be null if there is audio stream. 291 // |update_current_time_cb_| might be null if there is audio stream.
276 // Do not update current time for stand-alone EOS frames. 292 // Do not update current time for stand-alone EOS frames.
277 if (!update_current_time_cb_.is_null() && !(eos_encountered && !size)) { 293 if (!update_current_time_cb_.is_null() && !(eos_encountered && !size)) {
278 media_task_runner_->PostTask(FROM_HERE, 294 media_task_runner_->PostTask(FROM_HERE,
279 base::Bind(update_current_time_cb_, pts, pts)); 295 base::Bind(update_current_time_cb_, pts, pts));
280 } 296 }
281 } 297 }
282 298
283 } // namespace media 299 } // namespace media
OLDNEW
« media/base/android/media_codec_player.cc ('K') | « media/base/android/media_codec_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698