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

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

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix several more bot-identified build issues Created 4 years, 8 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 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 "media/gpu/android_video_encode_accelerator.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "content/common/gpu/media/shared_memory_region.h"
14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
15 #include "gpu/ipc/service/gpu_channel.h" 14 #include "gpu/ipc/service/gpu_channel.h"
16 #include "media/base/android/media_codec_util.h" 15 #include "media/base/android/media_codec_util.h"
17 #include "media/base/bitstream_buffer.h" 16 #include "media/base/bitstream_buffer.h"
18 #include "media/base/limits.h" 17 #include "media/base/limits.h"
18 #include "media/gpu/shared_memory_region.h"
19 #include "media/video/picture.h" 19 #include "media/video/picture.h"
20 #include "third_party/libyuv/include/libyuv/convert_from.h" 20 #include "third_party/libyuv/include/libyuv/convert_from.h"
21 #include "ui/gl/android/scoped_java_surface.h" 21 #include "ui/gl/android/scoped_java_surface.h"
22 #include "ui/gl/gl_bindings.h" 22 #include "ui/gl/gl_bindings.h"
23 23
24 using media::VideoCodecBridge; 24 using media::VideoCodecBridge;
25 using media::VideoFrame; 25 using media::VideoFrame;
26 26
27 namespace content { 27 namespace media {
28 28
29 // Limit default max video codec size for Android to avoid 29 // Limit default max video codec size for Android to avoid
30 // HW codec initialization failure for resolution higher than 720p. 30 // HW codec initialization failure for resolution higher than 720p.
31 // Default values are from Libjingle "jsepsessiondescription.cc". 31 // Default values are from Libjingle "jsepsessiondescription.cc".
32 const int kMaxEncodeFrameWidth = 1280; 32 const int kMaxEncodeFrameWidth = 1280;
33 const int kMaxEncodeFrameHeight = 720; 33 const int kMaxEncodeFrameHeight = 720;
34 const int kMaxFramerateNumerator = 30; 34 const int kMaxFramerateNumerator = 30;
35 const int kMaxFramerateDenominator = 1; 35 const int kMaxFramerateDenominator = 1;
36 36
37 enum PixelFormat { 37 enum PixelFormat {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; 86 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
87 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0) 87 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0)
88 *pixel_format = COLOR_FORMAT_YUV420_PLANAR; 88 *pixel_format = COLOR_FORMAT_YUV420_PLANAR;
89 else 89 else
90 return false; 90 return false;
91 91
92 return true; 92 return true;
93 } 93 }
94 94
95 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator() 95 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator()
96 : num_buffers_at_codec_(0), 96 : num_buffers_at_codec_(0), last_set_bitrate_(0) {}
97 last_set_bitrate_(0) {}
98 97
99 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { 98 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
100 DCHECK(thread_checker_.CalledOnValidThread()); 99 DCHECK(thread_checker_.CalledOnValidThread());
101 } 100 }
102 101
103 media::VideoEncodeAccelerator::SupportedProfiles 102 media::VideoEncodeAccelerator::SupportedProfiles
104 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { 103 AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
105 SupportedProfiles profiles; 104 SupportedProfiles profiles;
106 105
107 const struct { 106 const struct {
108 const media::VideoCodec codec; 107 const media::VideoCodec codec;
109 const media::VideoCodecProfile profile; 108 const media::VideoCodecProfile profile;
110 } kSupportedCodecs[] = { 109 } kSupportedCodecs[] = {{media::kCodecVP8, media::VP8PROFILE_ANY},
111 { media::kCodecVP8, media::VP8PROFILE_ANY }, 110 {media::kCodecH264, media::H264PROFILE_BASELINE},
112 { media::kCodecH264, media::H264PROFILE_BASELINE }, 111 {media::kCodecH264, media::H264PROFILE_MAIN}};
113 { media::kCodecH264, media::H264PROFILE_MAIN }
114 };
115 112
116 for (const auto& supported_codec : kSupportedCodecs) { 113 for (const auto& supported_codec : kSupportedCodecs) {
117 if (supported_codec.codec == media::kCodecVP8 && 114 if (supported_codec.codec == media::kCodecVP8 &&
118 !media::MediaCodecUtil::IsVp8EncoderAvailable()) { 115 !media::MediaCodecUtil::IsVp8EncoderAvailable()) {
119 continue; 116 continue;
120 } 117 }
121 118
122 if (VideoCodecBridge::IsKnownUnaccelerated(supported_codec.codec, 119 if (VideoCodecBridge::IsKnownUnaccelerated(supported_codec.codec,
123 media::MEDIA_CODEC_ENCODER)) { 120 media::MEDIA_CODEC_ENCODER)) {
124 continue; 121 continue;
125 } 122 }
126 123
127 SupportedProfile profile; 124 SupportedProfile profile;
128 profile.profile = supported_codec.profile; 125 profile.profile = supported_codec.profile;
129 // It would be nice if MediaCodec exposes the maximum capabilities of 126 // It would be nice if MediaCodec exposes the maximum capabilities of
130 // the encoder. Hard-code some reasonable defaults as workaround. 127 // the encoder. Hard-code some reasonable defaults as workaround.
131 profile.max_resolution.SetSize(kMaxEncodeFrameWidth, 128 profile.max_resolution.SetSize(kMaxEncodeFrameWidth, kMaxEncodeFrameHeight);
132 kMaxEncodeFrameHeight);
133 profile.max_framerate_numerator = kMaxFramerateNumerator; 129 profile.max_framerate_numerator = kMaxFramerateNumerator;
134 profile.max_framerate_denominator = kMaxFramerateDenominator; 130 profile.max_framerate_denominator = kMaxFramerateDenominator;
135 profiles.push_back(profile); 131 profiles.push_back(profile);
136 } 132 }
137 return profiles; 133 return profiles;
138 } 134 }
139 135
140 bool AndroidVideoEncodeAccelerator::Initialize( 136 bool AndroidVideoEncodeAccelerator::Initialize(
141 media::VideoPixelFormat format, 137 media::VideoPixelFormat format,
142 const gfx::Size& input_visible_size, 138 const gfx::Size& input_visible_size,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 codec, media::MEDIA_CODEC_ENCODER)) { 181 codec, media::MEDIA_CODEC_ENCODER)) {
186 DLOG(ERROR) << "No HW support"; 182 DLOG(ERROR) << "No HW support";
187 return false; 183 return false;
188 } 184 }
189 185
190 PixelFormat pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; 186 PixelFormat pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
191 if (!GetSupportedColorFormatForMime(mime_type, &pixel_format)) { 187 if (!GetSupportedColorFormatForMime(mime_type, &pixel_format)) {
192 DLOG(ERROR) << "No color format support."; 188 DLOG(ERROR) << "No color format support.";
193 return false; 189 return false;
194 } 190 }
195 media_codec_.reset(media::VideoCodecBridge::CreateEncoder(codec, 191 media_codec_.reset(media::VideoCodecBridge::CreateEncoder(
196 input_visible_size, 192 codec, input_visible_size, initial_bitrate, INITIAL_FRAMERATE,
197 initial_bitrate, 193 IFRAME_INTERVAL, pixel_format));
198 INITIAL_FRAMERATE,
199 IFRAME_INTERVAL,
200 pixel_format));
201 194
202 if (!media_codec_) { 195 if (!media_codec_) {
203 DLOG(ERROR) << "Failed to create/start the codec: " 196 DLOG(ERROR) << "Failed to create/start the codec: "
204 << input_visible_size.ToString(); 197 << input_visible_size.ToString();
205 return false; 198 return false;
206 } 199 }
207 200
208 // Conservative upper bound for output buffer size: decoded size + 2KB. 201 // Conservative upper bound for output buffer size: decoded size + 2KB.
209 const size_t output_buffer_capacity = 202 const size_t output_buffer_capacity =
210 VideoFrame::AllocationSize(format, input_visible_size) + 2048; 203 VideoFrame::AllocationSize(format, input_visible_size) + 2048;
211 base::MessageLoop::current()->PostTask( 204 base::MessageLoop::current()->PostTask(
212 FROM_HERE, 205 FROM_HERE,
213 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers, 206 base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers,
214 client_ptr_factory_->GetWeakPtr(), 207 client_ptr_factory_->GetWeakPtr(), frame_input_count,
215 frame_input_count, 208 input_visible_size, output_buffer_capacity));
216 input_visible_size,
217 output_buffer_capacity));
218 return true; 209 return true;
219 } 210 }
220 211
221 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() { 212 void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() {
222 if (!io_timer_.IsRunning() && 213 if (!io_timer_.IsRunning() &&
223 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) { 214 (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) {
224 io_timer_.Start(FROM_HERE, 215 io_timer_.Start(FROM_HERE, EncodePollDelay(), this,
225 EncodePollDelay(),
226 this,
227 &AndroidVideoEncodeAccelerator::DoIOTask); 216 &AndroidVideoEncodeAccelerator::DoIOTask);
228 } 217 }
229 } 218 }
230 219
231 void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() { 220 void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() {
232 if (io_timer_.IsRunning() && 221 if (io_timer_.IsRunning() &&
233 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) { 222 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) {
234 io_timer_.Stop(); 223 io_timer_.Stop();
235 } 224 }
236 } 225 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 void AndroidVideoEncodeAccelerator::QueueInput() { 296 void AndroidVideoEncodeAccelerator::QueueInput() {
308 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty()) 297 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty())
309 return; 298 return;
310 299
311 int input_buf_index = 0; 300 int input_buf_index = 0;
312 media::MediaCodecStatus status = 301 media::MediaCodecStatus status =
313 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); 302 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index);
314 if (status != media::MEDIA_CODEC_OK) { 303 if (status != media::MEDIA_CODEC_OK) {
315 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || 304 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER ||
316 status == media::MEDIA_CODEC_ERROR); 305 status == media::MEDIA_CODEC_ERROR);
317 RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR, 306 RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR, "MediaCodec error",
318 "MediaCodec error",
319 kPlatformFailureError); 307 kPlatformFailureError);
320 return; 308 return;
321 } 309 }
322 310
323 const PendingFrames::value_type& input = pending_frames_.front(); 311 const PendingFrames::value_type& input = pending_frames_.front();
324 bool is_key_frame = base::get<1>(input); 312 bool is_key_frame = base::get<1>(input);
325 if (is_key_frame) { 313 if (is_key_frame) {
326 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could 314 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could
327 // indicate this in the QueueInputBuffer() call below and guarantee _this_ 315 // indicate this in the QueueInputBuffer() call below and guarantee _this_
328 // frame be encoded as a key frame, but sadly that flag is ignored. 316 // frame be encoded as a key frame, but sadly that flag is ignored.
(...skipping 15 matching lines...) Expand all
344 kPlatformFailureError); 332 kPlatformFailureError);
345 333
346 uint8_t* dst_y = buffer; 334 uint8_t* dst_y = buffer;
347 int dst_stride_y = frame->stride(VideoFrame::kYPlane); 335 int dst_stride_y = frame->stride(VideoFrame::kYPlane);
348 uint8_t* dst_uv = 336 uint8_t* dst_uv =
349 buffer + 337 buffer +
350 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane); 338 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane);
351 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; 339 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2;
352 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other 340 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other
353 // mention of that constant. 341 // mention of that constant.
354 bool converted = !libyuv::I420ToNV12(frame->data(VideoFrame::kYPlane), 342 bool converted = !libyuv::I420ToNV12(
355 frame->stride(VideoFrame::kYPlane), 343 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane),
356 frame->data(VideoFrame::kUPlane), 344 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane),
357 frame->stride(VideoFrame::kUPlane), 345 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane),
358 frame->data(VideoFrame::kVPlane), 346 dst_y, dst_stride_y, dst_uv, dst_stride_uv, frame->coded_size().width(),
359 frame->stride(VideoFrame::kVPlane), 347 frame->coded_size().height());
360 dst_y,
361 dst_stride_y,
362 dst_uv,
363 dst_stride_uv,
364 frame->coded_size().width(),
365 frame->coded_size().height());
366 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); 348 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError);
367 349
368 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); 350 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1);
369 status = media_codec_->QueueInputBuffer( 351 status = media_codec_->QueueInputBuffer(input_buf_index, NULL, queued_size,
370 input_buf_index, NULL, queued_size, fake_input_timestamp_); 352 fake_input_timestamp_);
371 UMA_HISTOGRAM_TIMES("Media.AVEA.InputQueueTime", 353 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime",
372 base::Time::Now() - base::get<2>(input)); 354 base::Time::Now() - base::get<2>(input));
373 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, 355 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
374 "Failed to QueueInputBuffer: " << status, 356 "Failed to QueueInputBuffer: " << status,
375 kPlatformFailureError); 357 kPlatformFailureError);
376 ++num_buffers_at_codec_; 358 ++num_buffers_at_codec_;
377 pending_frames_.pop(); 359 pending_frames_.pop();
378 } 360 }
379 361
380 void AndroidVideoEncodeAccelerator::DequeueOutput() { 362 void AndroidVideoEncodeAccelerator::DequeueOutput() {
381 if (!client_ptr_factory_->GetWeakPtr() || 363 if (!client_ptr_factory_->GetWeakPtr() ||
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 "Encoded buffer too large: " << size << ">" << shm->size(), 408 "Encoded buffer too large: " << size << ">" << shm->size(),
427 kPlatformFailureError); 409 kPlatformFailureError);
428 410
429 media::MediaCodecStatus status = media_codec_->CopyFromOutputBuffer( 411 media::MediaCodecStatus status = media_codec_->CopyFromOutputBuffer(
430 buf_index, offset, shm->memory(), size); 412 buf_index, offset, shm->memory(), size);
431 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, 413 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
432 "CopyFromOutputBuffer failed", kPlatformFailureError); 414 "CopyFromOutputBuffer failed", kPlatformFailureError);
433 media_codec_->ReleaseOutputBuffer(buf_index, false); 415 media_codec_->ReleaseOutputBuffer(buf_index, false);
434 --num_buffers_at_codec_; 416 --num_buffers_at_codec_;
435 417
436 UMA_HISTOGRAM_COUNTS_10000("Media.AVEA.EncodedBufferSizeKB", size / 1024);
437 base::MessageLoop::current()->PostTask( 418 base::MessageLoop::current()->PostTask(
438 FROM_HERE, 419 FROM_HERE,
439 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, 420 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady,
440 client_ptr_factory_->GetWeakPtr(), 421 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size,
441 bitstream_buffer.id(),
442 size,
443 key_frame)); 422 key_frame));
444 } 423 }
445 424
446 } // namespace content 425 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698