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

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: 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 SetTimeCallback& update_current_time_cb,
25 const base::Closure& request_resources_cb)
26 : MediaCodecDecoder(media_task_runner, ui_task_runner,
27 request_data_cb, starvation_cb,
28 stop_done_cb, error_cb, update_current_time_cb,
29 "VideoDecoder"),
30 request_resources_cb_(request_resources_cb)
31 {}
32
33 MediaCodecVideoDecoder::~MediaCodecVideoDecoder()
34 {
35 DVLOG(1) << "VideoDecoder::~VideoDecoder()";
36 }
37
38 void MediaCodecVideoDecoder::SetPendingSurface(gfx::ScopedJavaSurface surface) {
39 // Media thread
40 surface_ = surface.Pass();
41
42 if (surface_.IsEmpty()) {
43 // Synchronously stop decoder thread and release MediaCodec
44 ReleaseDecoderResources();
45 }
46 }
47
48 bool MediaCodecVideoDecoder::HasPendingSurface() const {
49 return !surface_.IsEmpty();
50 }
51
52 bool MediaCodecVideoDecoder::HasStream() const {
53 return configs_.video_codec != kUnknownVideoCodec;
54 }
55
56 int MediaCodecVideoDecoder::GetVideoWidth() const {
57 base::AutoLock lock(configs_lock_);
58 return configs_.video_size.width();
59 }
60
61 int MediaCodecVideoDecoder::GetVideoHeight() const {
62 base::AutoLock lock(configs_lock_);
63 return configs_.video_size.height();
64 }
65
66 bool MediaCodecVideoDecoder::IsCodecReconfigureNeeded(
67 const DemuxerConfigs& curr, const DemuxerConfigs& next) const {
68
69 if (curr.video_codec != next.video_codec ||
70 curr.is_video_encrypted != next.is_video_encrypted)
71 return true;
72
73 // Only size changes below this point
74
75 if (curr.video_size.width() == next.video_size.width() &&
76 curr.video_size.height() == next.video_size.height())
77 return false; // i.e. curr == next
78
79 return !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())->
80 IsAdaptivePlaybackSupported(next.video_size.width(),
81 next.video_size.height());
82 }
83
84 MediaCodecDecoder::ConfigStatus
85 MediaCodecVideoDecoder::ConfigureInternal() {
86 DVLOG(1) << class_name() << "::" << __FUNCTION__;
87
88 // If we cannot find a key frame in cache, the browser seek is needed.
89 if (! au_queue_.SkipToKeyFrame()) {
90 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " key frame required";
91
92 // The processing of CONFIG_KEY_FRAME_REQUIRED is not implemented yet,
93 // return error for now
94 //return CONFIG_KEY_FRAME_REQUIRED;
95 return CONFIG_FAILURE;
96 }
97
98 //bool is_secure = is_content_encrypted() && drm_bridge() &&
99 // drm_bridge()->IsProtectedSurfaceRequired();
100
101 bool is_secure = false; // DRM is not implemented
102
103 DCHECK(!surface_.IsEmpty());
104
105 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder(
106 configs_.video_codec,
107 is_secure,
108 configs_.video_size,
109 surface_.j_surface().obj(),
110 GetMediaCrypto().obj()));
111
112 if (!media_codec_bridge_) {
113 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " failed";
114 return CONFIG_FAILURE;
115 }
116
117 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded";
118
119 // This callback requests resources by releasing other players,
120 // post it to the UI thread.
121 ui_task_runner_->PostTask(FROM_HERE, request_resources_cb_);
122
123 return CONFIG_OK;
124 }
125
126 void MediaCodecVideoDecoder::ReleaseDecoderResources() {
127 DVLOG(1) << class_name() << "::" << __FUNCTION__;
128
129 MediaCodecDecoder::ReleaseDecoderResources();
130 surface_ = gfx::ScopedJavaSurface();
131 delayed_buffers_.clear();
132 }
133
134 void MediaCodecVideoDecoder::Render(int buffer_index,
135 size_t size,
136 bool render_output,
137 base::TimeDelta pts,
138 bool eos_encountered) {
139 // Decoder thread
140 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts;
141
142 if (!render_output || size == 0u) {
143 ReleaseOutputBuffer(buffer_index, false, eos_encountered);
144 return;
145 }
146
147 base::TimeDelta time_to_render =
148 pts - (base::TimeTicks::Now() - start_time_ticks_ + start_pts_);
149
150 if (time_to_render < base::TimeDelta()) {
151 // Skip late frames
152 ReleaseOutputBuffer(buffer_index, false, eos_encountered);
153 return;
154 }
155
156 delayed_buffers_.insert(buffer_index);
157
158 decoder_thread_.task_runner()->PostDelayedTask(
159 FROM_HERE,
160 base::Bind(&MediaCodecVideoDecoder::ReleaseOutputBuffer,
161 base::Unretained(this),
162 buffer_index, true, eos_encountered),
163 time_to_render);
164 }
165
166 void MediaCodecVideoDecoder::ReleaseOutputBuffer(
167 int buffer_index, bool render, bool eos_encountered) {
168 DVLOG(2) << class_name() << "::" << __FUNCTION__;
169
170 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, render);
171
172 delayed_buffers_.erase(buffer_index);
173
174 bool last_frame_when_stopping =
175 GetState() == STOPPING && delayed_buffers_.empty();
176
177 if (last_frame_when_stopping || eos_encountered) {
178 SetState(STOPPED);
179 media_task_runner_->PostTask(
180 FROM_HERE,
181 base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
182 weak_this_, eos_encountered));
183 }
184 }
185
186 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const {
187 // Decoder thread
188 return delayed_buffers_.size();
189 }
190
191 void MediaCodecVideoDecoder::ReleaseDelayedBuffers() {
192 // Media thread
193 // Called when there is no decoder thread
194 for (int index : delayed_buffers_)
195 media_codec_bridge_->ReleaseOutputBuffer(index, false);
196 delayed_buffers_.clear();
197 }
198
199 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698