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

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

Issue 1128383003: Implementation of MediaCodecPlayer stage 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Min comments, added DCHECKs for current threads Created 5 years, 7 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/android/media_codec_video_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9
10 #include "media/base/android/media_codec_bridge.h"
11 #include "media/base/demuxer_stream.h"
12
13 //#include "base/tvlog.h"
14
15 namespace media {
16
17 MediaCodecVideoDecoder::MediaCodecVideoDecoder(
18 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
19 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
20 const base::Closure& request_data_cb,
21 const base::Closure& starvation_cb,
22 const base::Closure& stop_done_cb,
23 const base::Closure& error_cb,
24 const base::Closure& request_resources_cb)
25 : MediaCodecDecoder(media_task_runner,
26 ui_task_runner,
27 request_data_cb,
28 starvation_cb,
29 stop_done_cb,
30 error_cb,
31 "VideoDecoder"),
32 request_resources_cb_(request_resources_cb)
33 {}
34
35 MediaCodecVideoDecoder::~MediaCodecVideoDecoder()
36 {
37 DVLOG(1) << "VideoDecoder::~VideoDecoder()";
38 }
39
40 void MediaCodecVideoDecoder::SetPendingSurface(gfx::ScopedJavaSurface surface) {
41 // Media thread
42 DCHECK(media_task_runner_->BelongsToCurrentThread());
43
44 surface_ = surface.Pass();
45
46 if (surface_.IsEmpty()) {
47 // Synchronously stop decoder thread and release MediaCodec
48 ReleaseDecoderResources();
49 }
50 }
51
52 bool MediaCodecVideoDecoder::HasPendingSurface() const {
53 // Media thread
54 DCHECK(media_task_runner_->BelongsToCurrentThread());
55
56 return !surface_.IsEmpty();
57 }
58
59 bool MediaCodecVideoDecoder::HasStream() const {
60 // Media thread
61 DCHECK(media_task_runner_->BelongsToCurrentThread());
62
63 return configs_.video_codec != kUnknownVideoCodec;
64 }
65
66 int MediaCodecVideoDecoder::GetVideoWidth() const {
67 // UI thread, Media thread
68 base::AutoLock lock(configs_lock_);
69 return configs_.video_size.width();
70 }
71
72 int MediaCodecVideoDecoder::GetVideoHeight() const {
73 // UI thread, Media thread
74 base::AutoLock lock(configs_lock_);
75 return configs_.video_size.height();
76 }
77
78 bool MediaCodecVideoDecoder::IsCodecReconfigureNeeded(
79 const DemuxerConfigs& curr, const DemuxerConfigs& next) const {
80
81 if (curr.video_codec != next.video_codec ||
82 curr.is_video_encrypted != next.is_video_encrypted)
83 return true;
84
85 // Only size changes below this point
86
87 if (curr.video_size.width() == next.video_size.width() &&
88 curr.video_size.height() == next.video_size.height())
89 return false; // i.e. curr == next
90
91 return !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())->
92 IsAdaptivePlaybackSupported(next.video_size.width(),
93 next.video_size.height());
94 }
95
96 MediaCodecDecoder::ConfigStatus
97 MediaCodecVideoDecoder::ConfigureInternal() {
98 // Media thread
99 DCHECK(media_task_runner_->BelongsToCurrentThread());
100
101 DVLOG(1) << class_name() << "::" << __FUNCTION__;
102
103 // If we cannot find a key frame in cache, the browser seek is needed.
104 if (! au_queue_.SkipToKeyFrame()) {
qinmin 2015/05/13 23:17:32 extra space after !
Tima Vaisburd 2015/05/14 00:14:59 Oops! Removed.
105 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " key frame required";
106
107 // The processing of CONFIG_KEY_FRAME_REQUIRED is not implemented yet,
108 // return error for now
109 //return CONFIG_KEY_FRAME_REQUIRED;
110 return CONFIG_FAILURE;
111 }
112
113 //bool is_secure = is_content_encrypted() && drm_bridge() &&
114 // drm_bridge()->IsProtectedSurfaceRequired();
115
116 bool is_secure = false; // DRM is not implemented
117
118 DCHECK(!surface_.IsEmpty());
119
120 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder(
121 configs_.video_codec,
122 is_secure,
123 configs_.video_size,
124 surface_.j_surface().obj(),
125 GetMediaCrypto().obj()));
126
127 if (!media_codec_bridge_) {
128 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " failed";
129 return CONFIG_FAILURE;
130 }
131
132 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded";
133
134 // This callback requests resources by releasing other players,
135 // post it to the UI thread.
136 ui_task_runner_->PostTask(FROM_HERE, request_resources_cb_);
137
138 return CONFIG_OK;
139 }
140
141 void MediaCodecVideoDecoder::ReleaseDecoderResources() {
142 // Media thread
143 DCHECK(media_task_runner_->BelongsToCurrentThread());
144
145 DVLOG(1) << class_name() << "::" << __FUNCTION__;
146
147 MediaCodecDecoder::ReleaseDecoderResources();
148 surface_ = gfx::ScopedJavaSurface();
149 delayed_buffers_.clear();
150 }
151
152 void MediaCodecVideoDecoder::SynchronizePTSWithTime(
153 base::TimeDelta current_time) {
154 // Media thread
155 DCHECK(media_task_runner_->BelongsToCurrentThread());
156
157 start_time_ticks_ = base::TimeTicks::Now();
158 start_pts_ = current_time;
159 }
160
161 void MediaCodecVideoDecoder::Render(int buffer_index,
162 size_t size,
163 bool render_output,
164 base::TimeDelta pts,
165 bool eos_encountered) {
166 // Decoder thread
167 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
168
169 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts;
170
171 if (!render_output || size == 0u) {
172 ReleaseOutputBuffer(buffer_index, false, eos_encountered);
173 return;
174 }
175
176 base::TimeDelta time_to_render =
177 pts - (base::TimeTicks::Now() - start_time_ticks_ + start_pts_);
178
179 if (time_to_render < base::TimeDelta()) {
180 // Skip late frames
181 ReleaseOutputBuffer(buffer_index, false, eos_encountered);
182 return;
183 }
184
185 delayed_buffers_.insert(buffer_index);
186
187 decoder_thread_.task_runner()->PostDelayedTask(
188 FROM_HERE,
189 base::Bind(&MediaCodecVideoDecoder::ReleaseOutputBuffer,
190 base::Unretained(this),
191 buffer_index, true, eos_encountered),
192 time_to_render);
193 }
194
195 void MediaCodecVideoDecoder::ReleaseOutputBuffer(
196 int buffer_index, bool render, bool eos_encountered) {
197 // Decoder thread
198 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
199
200 DVLOG(2) << class_name() << "::" << __FUNCTION__;
201
202 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, render);
203
204 delayed_buffers_.erase(buffer_index);
205
206 ProcessLastFrame(eos_encountered, !delayed_buffers_.empty());
207 }
208
209 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const {
210 // Decoder thread
211 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
212
213 return delayed_buffers_.size();
214 }
215
216 void MediaCodecVideoDecoder::ReleaseDelayedBuffers() {
217 // Media thread
218 // Called when there is no decoder thread
219 for (int index : delayed_buffers_)
220 media_codec_bridge_->ReleaseOutputBuffer(index, false);
221 delayed_buffers_.clear();
222 }
223
224 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698