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

Side by Side Diff: content/common/gpu/media/android_video_encode_accelerator.cc

Issue 170843004: Pass Client pointer in Initialize() for VDA/VEA (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 50e826de Rebase. Created 6 years, 9 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/common/gpu/media/android_video_encode_accelerator.h" 5 #include "content/common/gpu/media/android_video_encode_accelerator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
(...skipping 15 matching lines...) Expand all
26 26
27 namespace content { 27 namespace content {
28 28
29 enum { 29 enum {
30 // Subset of MediaCodecInfo.CodecCapabilities. 30 // Subset of MediaCodecInfo.CodecCapabilities.
31 COLOR_FORMAT_YUV420_SEMIPLANAR = 21, 31 COLOR_FORMAT_YUV420_SEMIPLANAR = 21,
32 }; 32 };
33 33
34 // Helper macros for dealing with failure. If |result| evaluates false, emit 34 // Helper macros for dealing with failure. If |result| evaluates false, emit
35 // |log| to DLOG(ERROR), register |error| with the client, and return. 35 // |log| to DLOG(ERROR), register |error| with the client, and return.
36 #define RETURN_ON_FAILURE(result, log, error) \ 36 #define RETURN_ON_FAILURE(result, log, error) \
37 do { \ 37 do { \
38 if (!(result)) { \ 38 if (!(result)) { \
39 DLOG(ERROR) << log; \ 39 DLOG(ERROR) << log; \
40 if (client_ptr_factory_.GetWeakPtr()) { \ 40 if (client_ptr_factory_->GetWeakPtr()) { \
41 client_ptr_factory_.GetWeakPtr()->NotifyError(error); \ 41 client_ptr_factory_->GetWeakPtr()->NotifyError(error); \
42 client_ptr_factory_.InvalidateWeakPtrs(); \ 42 client_ptr_factory_.reset(); \
43 } \ 43 } \
44 return; \ 44 return; \
45 } \ 45 } \
46 } while (0) 46 } while (0)
47 47
48 // Because MediaCodec is thread-hostile (must be poked on a single thread) and 48 // Because MediaCodec is thread-hostile (must be poked on a single thread) and
49 // has no callback mechanism (b/11990118), we must drive it by polling for 49 // has no callback mechanism (b/11990118), we must drive it by polling for
50 // complete frames (and available input buffers, when the codec is fully 50 // complete frames (and available input buffers, when the codec is fully
51 // saturated). This function defines the polling delay. The value used is an 51 // saturated). This function defines the polling delay. The value used is an
52 // arbitrary choice that trades off CPU utilization (spinning) against latency. 52 // arbitrary choice that trades off CPU utilization (spinning) against latency.
53 // Mirrors android_video_decode_accelerator.cc::DecodePollDelay(). 53 // Mirrors android_video_decode_accelerator.cc::DecodePollDelay().
54 static inline const base::TimeDelta EncodePollDelay() { 54 static inline const base::TimeDelta EncodePollDelay() {
55 // An alternative to this polling scheme could be to dedicate a new thread 55 // An alternative to this polling scheme could be to dedicate a new thread
56 // (instead of using the ChildThread) to run the MediaCodec, and make that 56 // (instead of using the ChildThread) to run the MediaCodec, and make that
57 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it 57 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it
58 // believes the codec should complete "soon" (e.g. waiting for an input 58 // believes the codec should complete "soon" (e.g. waiting for an input
59 // buffer, or waiting for a picture when it knows enough complete input 59 // buffer, or waiting for a picture when it knows enough complete input
60 // pictures have been fed to saturate any internal buffering). This is 60 // pictures have been fed to saturate any internal buffering). This is
61 // speculative and it's unclear that this would be a win (nor that there's a 61 // speculative and it's unclear that this would be a win (nor that there's a
62 // reasonably device-agnostic way to fill in the "believes" above). 62 // reasonably device-agnostic way to fill in the "believes" above).
63 return base::TimeDelta::FromMilliseconds(10); 63 return base::TimeDelta::FromMilliseconds(10);
64 } 64 }
65 65
66 static inline const base::TimeDelta NoWaitTimeOut() { 66 static inline const base::TimeDelta NoWaitTimeOut() {
67 return base::TimeDelta::FromMicroseconds(0); 67 return base::TimeDelta::FromMicroseconds(0);
68 } 68 }
69 69
70 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator( 70 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator()
71 media::VideoEncodeAccelerator::Client* client) 71 : num_buffers_at_codec_(0),
72 : client_ptr_factory_(client),
73 num_buffers_at_codec_(0),
74 num_output_buffers_(-1), 72 num_output_buffers_(-1),
75 output_buffers_capacity_(0), 73 output_buffers_capacity_(0),
76 last_set_bitrate_(0) {} 74 last_set_bitrate_(0) {}
77 75
78 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { 76 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
79 DCHECK(thread_checker_.CalledOnValidThread()); 77 DCHECK(thread_checker_.CalledOnValidThread());
80 } 78 }
81 79
82 // static 80 // static
83 std::vector<media::VideoEncodeAccelerator::SupportedProfile> 81 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
(...skipping 27 matching lines...) Expand all
111 profile.max_framerate.denominator = 1; 109 profile.max_framerate.denominator = 1;
112 profiles.push_back(profile); 110 profiles.push_back(profile);
113 } 111 }
114 return profiles; 112 return profiles;
115 } 113 }
116 114
117 void AndroidVideoEncodeAccelerator::Initialize( 115 void AndroidVideoEncodeAccelerator::Initialize(
118 VideoFrame::Format format, 116 VideoFrame::Format format,
119 const gfx::Size& input_visible_size, 117 const gfx::Size& input_visible_size,
120 media::VideoCodecProfile output_profile, 118 media::VideoCodecProfile output_profile,
121 uint32 initial_bitrate) { 119 uint32 initial_bitrate,
120 Client* client) {
122 DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format 121 DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format
123 << ", input_visible_size: " << input_visible_size.ToString() 122 << ", input_visible_size: " << input_visible_size.ToString()
124 << ", output_profile: " << output_profile 123 << ", output_profile: " << output_profile
125 << ", initial_bitrate: " << initial_bitrate; 124 << ", initial_bitrate: " << initial_bitrate;
126 DCHECK(!media_codec_); 125 DCHECK(!media_codec_);
127 DCHECK(thread_checker_.CalledOnValidThread()); 126 DCHECK(thread_checker_.CalledOnValidThread());
128 127
128 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
129
129 RETURN_ON_FAILURE(media::MediaCodecBridge::IsAvailable() && 130 RETURN_ON_FAILURE(media::MediaCodecBridge::IsAvailable() &&
130 media::MediaCodecBridge::SupportsSetParameters() && 131 media::MediaCodecBridge::SupportsSetParameters() &&
131 format == VideoFrame::I420 && 132 format == VideoFrame::I420 &&
132 output_profile == media::VP8PROFILE_MAIN, 133 output_profile == media::VP8PROFILE_MAIN,
133 "Unexpected combo: " << format << ", " << output_profile, 134 "Unexpected combo: " << format << ", " << output_profile,
134 kInvalidArgumentError); 135 kInvalidArgumentError);
135 136
136 last_set_bitrate_ = initial_bitrate; 137 last_set_bitrate_ = initial_bitrate;
137 138
138 // Only consider using MediaCodec if it's likely backed by hardware. 139 // Only consider using MediaCodec if it's likely backed by hardware.
(...skipping 15 matching lines...) Expand all
154 COLOR_FORMAT_YUV420_SEMIPLANAR)); 155 COLOR_FORMAT_YUV420_SEMIPLANAR));
155 156
156 RETURN_ON_FAILURE( 157 RETURN_ON_FAILURE(
157 media_codec_, 158 media_codec_,
158 "Failed to create/start the codec: " << input_visible_size.ToString(), 159 "Failed to create/start the codec: " << input_visible_size.ToString(),
159 kPlatformFailureError); 160 kPlatformFailureError);
160 161
161 base::MessageLoop::current()->PostTask( 162 base::MessageLoop::current()->PostTask(
162 FROM_HERE, 163 FROM_HERE,
163 base::Bind(&VideoEncodeAccelerator::Client::NotifyInitializeDone, 164 base::Bind(&VideoEncodeAccelerator::Client::NotifyInitializeDone,
164 client_ptr_factory_.GetWeakPtr())); 165 client_ptr_factory_->GetWeakPtr()));
165 166
166 num_output_buffers_ = media_codec_->GetOutputBuffersCount(); 167 num_output_buffers_ = media_codec_->GetOutputBuffersCount();
167 output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity(); 168 output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity();
168 base::MessageLoop::current()->PostTask( 169 base::MessageLoop::current()->PostTask(
169 FROM_HERE, 170 FROM_HERE,
170 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers, 171 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers,
171 client_ptr_factory_.GetWeakPtr(), 172 client_ptr_factory_->GetWeakPtr(),
172 num_output_buffers_, 173 num_output_buffers_,
173 input_visible_size, 174 input_visible_size,
174 output_buffers_capacity_)); 175 output_buffers_capacity_));
175 } 176 }
176 177
177 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() { 178 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() {
178 if (!io_timer_.IsRunning() && 179 if (!io_timer_.IsRunning() &&
179 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) { 180 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) {
180 io_timer_.Start(FROM_HERE, 181 io_timer_.Start(FROM_HERE,
181 EncodePollDelay(), 182 EncodePollDelay(),
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 240 }
240 // Note: Android's MediaCodec doesn't allow mid-stream adjustments to 241 // Note: Android's MediaCodec doesn't allow mid-stream adjustments to
241 // framerate, so we ignore that here. This is OK because Android only uses 242 // framerate, so we ignore that here. This is OK because Android only uses
242 // the framerate value from MediaFormat during configure() as a proxy for 243 // the framerate value from MediaFormat during configure() as a proxy for
243 // bitrate, and we set that explicitly. 244 // bitrate, and we set that explicitly.
244 } 245 }
245 246
246 void AndroidVideoEncodeAccelerator::Destroy() { 247 void AndroidVideoEncodeAccelerator::Destroy() {
247 DVLOG(3) << __PRETTY_FUNCTION__; 248 DVLOG(3) << __PRETTY_FUNCTION__;
248 DCHECK(thread_checker_.CalledOnValidThread()); 249 DCHECK(thread_checker_.CalledOnValidThread());
249 client_ptr_factory_.InvalidateWeakPtrs(); 250 client_ptr_factory_.reset();
250 if (media_codec_) { 251 if (media_codec_) {
251 if (io_timer_.IsRunning()) 252 if (io_timer_.IsRunning())
252 io_timer_.Stop(); 253 io_timer_.Stop();
253 media_codec_->Stop(); 254 media_codec_->Stop();
254 } 255 }
255 delete this; 256 delete this;
256 } 257 }
257 258
258 void AndroidVideoEncodeAccelerator::DoIOTask() { 259 void AndroidVideoEncodeAccelerator::DoIOTask() {
259 QueueInput(); 260 QueueInput();
260 DequeueOutput(); 261 DequeueOutput();
261 MaybeStartIOTimer(); 262 MaybeStartIOTimer();
262 MaybeStopIOTimer(); 263 MaybeStopIOTimer();
263 } 264 }
264 265
265 void AndroidVideoEncodeAccelerator::QueueInput() { 266 void AndroidVideoEncodeAccelerator::QueueInput() {
266 if (!client_ptr_factory_.GetWeakPtr() || pending_frames_.empty()) 267 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty())
267 return; 268 return;
268 269
269 int input_buf_index = 0; 270 int input_buf_index = 0;
270 media::MediaCodecStatus status = 271 media::MediaCodecStatus status =
271 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); 272 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index);
272 if (status != media::MEDIA_CODEC_OK) { 273 if (status != media::MEDIA_CODEC_OK) {
273 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || 274 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER ||
274 status == media::MEDIA_CODEC_ERROR); 275 status == media::MEDIA_CODEC_ERROR);
275 RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR, 276 RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR,
276 "MediaCodec error", 277 "MediaCodec error",
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 bool ret = media_codec_->GetOutputBuffers() && count <= num_output_buffers_ && 341 bool ret = media_codec_->GetOutputBuffers() && count <= num_output_buffers_ &&
341 capacity <= output_buffers_capacity_; 342 capacity <= output_buffers_capacity_;
342 LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: " 343 LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: "
343 << num_output_buffers_ << "x" << output_buffers_capacity_ 344 << num_output_buffers_ << "x" << output_buffers_capacity_
344 << ", now: " << count << "x" << capacity; 345 << ", now: " << count << "x" << capacity;
345 UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret); 346 UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret);
346 return ret; 347 return ret;
347 } 348 }
348 349
349 void AndroidVideoEncodeAccelerator::DequeueOutput() { 350 void AndroidVideoEncodeAccelerator::DequeueOutput() {
350 if (!client_ptr_factory_.GetWeakPtr() || 351 if (!client_ptr_factory_->GetWeakPtr() ||
351 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { 352 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) {
352 return; 353 return;
353 } 354 }
354 355
355 int32 buf_index = 0; 356 int32 buf_index = 0;
356 size_t offset = 0; 357 size_t offset = 0;
357 size_t size = 0; 358 size_t size = 0;
358 bool key_frame = false; 359 bool key_frame = false;
359 do { 360 do {
360 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 361 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 kPlatformFailureError); 399 kPlatformFailureError);
399 400
400 media_codec_->CopyFromOutputBuffer(buf_index, offset, shm->memory(), size); 401 media_codec_->CopyFromOutputBuffer(buf_index, offset, shm->memory(), size);
401 media_codec_->ReleaseOutputBuffer(buf_index, false); 402 media_codec_->ReleaseOutputBuffer(buf_index, false);
402 --num_buffers_at_codec_; 403 --num_buffers_at_codec_;
403 404
404 UMA_HISTOGRAM_COUNTS_10000("Media.AVEA.EncodedBufferSizeKB", size / 1024); 405 UMA_HISTOGRAM_COUNTS_10000("Media.AVEA.EncodedBufferSizeKB", size / 1024);
405 base::MessageLoop::current()->PostTask( 406 base::MessageLoop::current()->PostTask(
406 FROM_HERE, 407 FROM_HERE,
407 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, 408 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady,
408 client_ptr_factory_.GetWeakPtr(), 409 client_ptr_factory_->GetWeakPtr(),
409 bitstream_buffer.id(), 410 bitstream_buffer.id(),
410 size, 411 size,
411 key_frame)); 412 key_frame));
412 } 413 }
413 414
414 } // namespace content 415 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/android_video_encode_accelerator.h ('k') | content/common/gpu/media/dxva_video_decode_accelerator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698