OLD | NEW |
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 "media/gpu/android_video_encode_accelerator.h" | 5 #include "media/gpu/android_video_encode_accelerator.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <set> | 8 #include <set> |
9 #include <tuple> | 9 #include <tuple> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/location.h" | 12 #include "base/location.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
18 #include "gpu/ipc/service/gpu_channel.h" | 18 #include "gpu/ipc/service/gpu_channel.h" |
19 #include "media/base/android/media_codec_util.h" | 19 #include "media/base/android/media_codec_util.h" |
20 #include "media/base/bitstream_buffer.h" | 20 #include "media/base/bitstream_buffer.h" |
21 #include "media/base/limits.h" | 21 #include "media/base/limits.h" |
22 #include "media/gpu/shared_memory_region.h" | 22 #include "media/gpu/shared_memory_region.h" |
23 #include "media/video/picture.h" | 23 #include "media/video/picture.h" |
24 #include "third_party/libyuv/include/libyuv/convert_from.h" | 24 #include "third_party/libyuv/include/libyuv/convert_from.h" |
25 #include "ui/gl/android/scoped_java_surface.h" | 25 #include "ui/gl/android/scoped_java_surface.h" |
26 #include "ui/gl/gl_bindings.h" | 26 #include "ui/gl/gl_bindings.h" |
27 | 27 |
28 using media::VideoCodecBridge; | |
29 using media::VideoFrame; | |
30 | |
31 namespace media { | 28 namespace media { |
32 | 29 |
33 // Limit default max video codec size for Android to avoid | 30 // Limit default max video codec size for Android to avoid |
34 // HW codec initialization failure for resolution higher than 720p. | 31 // HW codec initialization failure for resolution higher than 720p. |
35 // Default values are from Libjingle "jsepsessiondescription.cc". | 32 // Default values are from Libjingle "jsepsessiondescription.cc". |
36 const int kMaxEncodeFrameWidth = 1280; | 33 const int kMaxEncodeFrameWidth = 1280; |
37 const int kMaxEncodeFrameHeight = 720; | 34 const int kMaxEncodeFrameHeight = 720; |
38 const int kMaxFramerateNumerator = 30; | 35 const int kMaxFramerateNumerator = 30; |
39 const int kMaxFramerateDenominator = 1; | 36 const int kMaxFramerateDenominator = 1; |
40 | 37 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 | 75 |
79 static inline const base::TimeDelta NoWaitTimeOut() { | 76 static inline const base::TimeDelta NoWaitTimeOut() { |
80 return base::TimeDelta::FromMicroseconds(0); | 77 return base::TimeDelta::FromMicroseconds(0); |
81 } | 78 } |
82 | 79 |
83 static bool GetSupportedColorFormatForMime(const std::string& mime, | 80 static bool GetSupportedColorFormatForMime(const std::string& mime, |
84 PixelFormat* pixel_format) { | 81 PixelFormat* pixel_format) { |
85 if (mime.empty()) | 82 if (mime.empty()) |
86 return false; | 83 return false; |
87 | 84 |
88 std::set<int> formats = media::MediaCodecUtil::GetEncoderColorFormats(mime); | 85 std::set<int> formats = MediaCodecUtil::GetEncoderColorFormats(mime); |
89 if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0) | 86 if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0) |
90 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; | 87 *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; |
91 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0) | 88 else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0) |
92 *pixel_format = COLOR_FORMAT_YUV420_PLANAR; | 89 *pixel_format = COLOR_FORMAT_YUV420_PLANAR; |
93 else | 90 else |
94 return false; | 91 return false; |
95 | 92 |
96 return true; | 93 return true; |
97 } | 94 } |
98 | 95 |
99 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator() | 96 AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator() |
100 : num_buffers_at_codec_(0), last_set_bitrate_(0) {} | 97 : num_buffers_at_codec_(0), last_set_bitrate_(0) {} |
101 | 98 |
102 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { | 99 AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { |
103 DCHECK(thread_checker_.CalledOnValidThread()); | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
104 } | 101 } |
105 | 102 |
106 media::VideoEncodeAccelerator::SupportedProfiles | 103 VideoEncodeAccelerator::SupportedProfiles |
107 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { | 104 AndroidVideoEncodeAccelerator::GetSupportedProfiles() { |
108 SupportedProfiles profiles; | 105 SupportedProfiles profiles; |
109 | 106 |
110 const struct { | 107 const struct { |
111 const media::VideoCodec codec; | 108 const VideoCodec codec; |
112 const media::VideoCodecProfile profile; | 109 const VideoCodecProfile profile; |
113 } kSupportedCodecs[] = {{media::kCodecVP8, media::VP8PROFILE_ANY}, | 110 } kSupportedCodecs[] = {{kCodecVP8, VP8PROFILE_ANY}, |
114 {media::kCodecH264, media::H264PROFILE_BASELINE}, | 111 {kCodecH264, H264PROFILE_BASELINE}, |
115 {media::kCodecH264, media::H264PROFILE_MAIN}}; | 112 {kCodecH264, H264PROFILE_MAIN}}; |
116 | 113 |
117 for (const auto& supported_codec : kSupportedCodecs) { | 114 for (const auto& supported_codec : kSupportedCodecs) { |
118 if (supported_codec.codec == media::kCodecVP8 && | 115 if (supported_codec.codec == kCodecVP8 && |
119 !media::MediaCodecUtil::IsVp8EncoderAvailable()) { | 116 !MediaCodecUtil::IsVp8EncoderAvailable()) { |
120 continue; | 117 continue; |
121 } | 118 } |
122 | 119 |
123 if (VideoCodecBridge::IsKnownUnaccelerated(supported_codec.codec, | 120 if (VideoCodecBridge::IsKnownUnaccelerated(supported_codec.codec, |
124 media::MEDIA_CODEC_ENCODER)) { | 121 MEDIA_CODEC_ENCODER)) { |
125 continue; | 122 continue; |
126 } | 123 } |
127 | 124 |
128 SupportedProfile profile; | 125 SupportedProfile profile; |
129 profile.profile = supported_codec.profile; | 126 profile.profile = supported_codec.profile; |
130 // It would be nice if MediaCodec exposes the maximum capabilities of | 127 // It would be nice if MediaCodec exposes the maximum capabilities of |
131 // the encoder. Hard-code some reasonable defaults as workaround. | 128 // the encoder. Hard-code some reasonable defaults as workaround. |
132 profile.max_resolution.SetSize(kMaxEncodeFrameWidth, kMaxEncodeFrameHeight); | 129 profile.max_resolution.SetSize(kMaxEncodeFrameWidth, kMaxEncodeFrameHeight); |
133 profile.max_framerate_numerator = kMaxFramerateNumerator; | 130 profile.max_framerate_numerator = kMaxFramerateNumerator; |
134 profile.max_framerate_denominator = kMaxFramerateDenominator; | 131 profile.max_framerate_denominator = kMaxFramerateDenominator; |
135 profiles.push_back(profile); | 132 profiles.push_back(profile); |
136 } | 133 } |
137 return profiles; | 134 return profiles; |
138 } | 135 } |
139 | 136 |
140 bool AndroidVideoEncodeAccelerator::Initialize( | 137 bool AndroidVideoEncodeAccelerator::Initialize( |
141 media::VideoPixelFormat format, | 138 VideoPixelFormat format, |
142 const gfx::Size& input_visible_size, | 139 const gfx::Size& input_visible_size, |
143 media::VideoCodecProfile output_profile, | 140 VideoCodecProfile output_profile, |
144 uint32_t initial_bitrate, | 141 uint32_t initial_bitrate, |
145 Client* client) { | 142 Client* client) { |
146 DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format | 143 DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format |
147 << ", input_visible_size: " << input_visible_size.ToString() | 144 << ", input_visible_size: " << input_visible_size.ToString() |
148 << ", output_profile: " << output_profile | 145 << ", output_profile: " << output_profile |
149 << ", initial_bitrate: " << initial_bitrate; | 146 << ", initial_bitrate: " << initial_bitrate; |
150 DCHECK(!media_codec_); | 147 DCHECK(!media_codec_); |
151 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
152 | 149 |
153 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 150 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
154 | 151 |
155 if (!(media::MediaCodecUtil::SupportsSetParameters() && | 152 if (!(MediaCodecUtil::SupportsSetParameters() && |
156 format == media::PIXEL_FORMAT_I420)) { | 153 format == PIXEL_FORMAT_I420)) { |
157 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; | 154 DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; |
158 return false; | 155 return false; |
159 } | 156 } |
160 | 157 |
161 std::string mime_type; | 158 std::string mime_type; |
162 media::VideoCodec codec; | 159 VideoCodec codec; |
163 // The client should be prepared to feed at least this many frames into the | 160 // The client should be prepared to feed at least this many frames into the |
164 // encoder before being returned any output frames, since the encoder may | 161 // encoder before being returned any output frames, since the encoder may |
165 // need to hold onto some subset of inputs as reference pictures. | 162 // need to hold onto some subset of inputs as reference pictures. |
166 uint32_t frame_input_count; | 163 uint32_t frame_input_count; |
167 if (output_profile == media::VP8PROFILE_ANY) { | 164 if (output_profile == VP8PROFILE_ANY) { |
168 codec = media::kCodecVP8; | 165 codec = kCodecVP8; |
169 mime_type = "video/x-vnd.on2.vp8"; | 166 mime_type = "video/x-vnd.on2.vp8"; |
170 frame_input_count = 1; | 167 frame_input_count = 1; |
171 } else if (output_profile == media::H264PROFILE_BASELINE || | 168 } else if (output_profile == H264PROFILE_BASELINE || |
172 output_profile == media::H264PROFILE_MAIN) { | 169 output_profile == H264PROFILE_MAIN) { |
173 codec = media::kCodecH264; | 170 codec = kCodecH264; |
174 mime_type = "video/avc"; | 171 mime_type = "video/avc"; |
175 frame_input_count = 30; | 172 frame_input_count = 30; |
176 } else { | 173 } else { |
177 return false; | 174 return false; |
178 } | 175 } |
179 | 176 |
180 frame_size_ = input_visible_size; | 177 frame_size_ = input_visible_size; |
181 last_set_bitrate_ = initial_bitrate; | 178 last_set_bitrate_ = initial_bitrate; |
182 | 179 |
183 // Only consider using MediaCodec if it's likely backed by hardware. | 180 // Only consider using MediaCodec if it's likely backed by hardware. |
184 if (media::VideoCodecBridge::IsKnownUnaccelerated( | 181 if (VideoCodecBridge::IsKnownUnaccelerated(codec, MEDIA_CODEC_ENCODER)) { |
185 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( | 191 media_codec_.reset(VideoCodecBridge::CreateEncoder( |
196 codec, input_visible_size, initial_bitrate, INITIAL_FRAMERATE, | 192 codec, input_visible_size, initial_bitrate, INITIAL_FRAMERATE, |
197 IFRAME_INTERVAL, pixel_format)); | 193 IFRAME_INTERVAL, pixel_format)); |
198 | 194 |
199 if (!media_codec_) { | 195 if (!media_codec_) { |
200 DLOG(ERROR) << "Failed to create/start the codec: " | 196 DLOG(ERROR) << "Failed to create/start the codec: " |
201 << input_visible_size.ToString(); | 197 << input_visible_size.ToString(); |
202 return false; | 198 return false; |
203 } | 199 } |
204 | 200 |
205 // Conservative upper bound for output buffer size: decoded size + 2KB. | 201 // Conservative upper bound for output buffer size: decoded size + 2KB. |
(...skipping 20 matching lines...) Expand all Loading... |
226 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) { | 222 (num_buffers_at_codec_ == 0 && pending_frames_.empty())) { |
227 io_timer_.Stop(); | 223 io_timer_.Stop(); |
228 } | 224 } |
229 } | 225 } |
230 | 226 |
231 void AndroidVideoEncodeAccelerator::Encode( | 227 void AndroidVideoEncodeAccelerator::Encode( |
232 const scoped_refptr<VideoFrame>& frame, | 228 const scoped_refptr<VideoFrame>& frame, |
233 bool force_keyframe) { | 229 bool force_keyframe) { |
234 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe; | 230 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe; |
235 DCHECK(thread_checker_.CalledOnValidThread()); | 231 DCHECK(thread_checker_.CalledOnValidThread()); |
236 RETURN_ON_FAILURE(frame->format() == media::PIXEL_FORMAT_I420, | 232 RETURN_ON_FAILURE(frame->format() == PIXEL_FORMAT_I420, "Unexpected format", |
237 "Unexpected format", kInvalidArgumentError); | 233 kInvalidArgumentError); |
238 RETURN_ON_FAILURE(frame->visible_rect().size() == frame_size_, | 234 RETURN_ON_FAILURE(frame->visible_rect().size() == frame_size_, |
239 "Unexpected resolution", kInvalidArgumentError); | 235 "Unexpected resolution", kInvalidArgumentError); |
240 // MediaCodec doesn't have a way to specify stride for non-Packed formats, so | 236 // MediaCodec doesn't have a way to specify stride for non-Packed formats, so |
241 // we insist on being called with packed frames and no cropping :( | 237 // we insist on being called with packed frames and no cropping :( |
242 RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) == | 238 RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) == |
243 frame->stride(VideoFrame::kYPlane) && | 239 frame->stride(VideoFrame::kYPlane) && |
244 frame->row_bytes(VideoFrame::kUPlane) == | 240 frame->row_bytes(VideoFrame::kUPlane) == |
245 frame->stride(VideoFrame::kUPlane) && | 241 frame->stride(VideoFrame::kUPlane) && |
246 frame->row_bytes(VideoFrame::kVPlane) == | 242 frame->row_bytes(VideoFrame::kVPlane) == |
247 frame->stride(VideoFrame::kVPlane) && | 243 frame->stride(VideoFrame::kVPlane) && |
248 frame->coded_size() == frame->visible_rect().size(), | 244 frame->coded_size() == frame->visible_rect().size(), |
249 "Non-packed frame, or visible_rect != coded_size", | 245 "Non-packed frame, or visible_rect != coded_size", |
250 kInvalidArgumentError); | 246 kInvalidArgumentError); |
251 | 247 |
252 pending_frames_.push( | 248 pending_frames_.push( |
253 std::make_tuple(frame, force_keyframe, base::Time::Now())); | 249 std::make_tuple(frame, force_keyframe, base::Time::Now())); |
254 DoIOTask(); | 250 DoIOTask(); |
255 } | 251 } |
256 | 252 |
257 void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 253 void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
258 const media::BitstreamBuffer& buffer) { | 254 const BitstreamBuffer& buffer) { |
259 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id(); | 255 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id(); |
260 DCHECK(thread_checker_.CalledOnValidThread()); | 256 DCHECK(thread_checker_.CalledOnValidThread()); |
261 available_bitstream_buffers_.push_back(buffer); | 257 available_bitstream_buffers_.push_back(buffer); |
262 DoIOTask(); | 258 DoIOTask(); |
263 } | 259 } |
264 | 260 |
265 void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange( | 261 void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange( |
266 uint32_t bitrate, | 262 uint32_t bitrate, |
267 uint32_t framerate) { | 263 uint32_t framerate) { |
268 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate | 264 DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate |
(...skipping 26 matching lines...) Expand all Loading... |
295 DequeueOutput(); | 291 DequeueOutput(); |
296 MaybeStartIOTimer(); | 292 MaybeStartIOTimer(); |
297 MaybeStopIOTimer(); | 293 MaybeStopIOTimer(); |
298 } | 294 } |
299 | 295 |
300 void AndroidVideoEncodeAccelerator::QueueInput() { | 296 void AndroidVideoEncodeAccelerator::QueueInput() { |
301 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty()) | 297 if (!client_ptr_factory_->GetWeakPtr() || pending_frames_.empty()) |
302 return; | 298 return; |
303 | 299 |
304 int input_buf_index = 0; | 300 int input_buf_index = 0; |
305 media::MediaCodecStatus status = | 301 MediaCodecStatus status = |
306 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); | 302 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); |
307 if (status != media::MEDIA_CODEC_OK) { | 303 if (status != MEDIA_CODEC_OK) { |
308 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || | 304 DCHECK(status == MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || |
309 status == media::MEDIA_CODEC_ERROR); | 305 status == MEDIA_CODEC_ERROR); |
310 RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR, "MediaCodec error", | 306 RETURN_ON_FAILURE(status != MEDIA_CODEC_ERROR, "MediaCodec error", |
311 kPlatformFailureError); | 307 kPlatformFailureError); |
312 return; | 308 return; |
313 } | 309 } |
314 | 310 |
315 const PendingFrames::value_type& input = pending_frames_.front(); | 311 const PendingFrames::value_type& input = pending_frames_.front(); |
316 bool is_key_frame = std::get<1>(input); | 312 bool is_key_frame = std::get<1>(input); |
317 if (is_key_frame) { | 313 if (is_key_frame) { |
318 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could | 314 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could |
319 // indicate this in the QueueInputBuffer() call below and guarantee _this_ | 315 // indicate this in the QueueInputBuffer() call below and guarantee _this_ |
320 // 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. |
321 // Instead, we request a key frame "soon". | 317 // Instead, we request a key frame "soon". |
322 media_codec_->RequestKeyFrameSoon(); | 318 media_codec_->RequestKeyFrameSoon(); |
323 } | 319 } |
324 scoped_refptr<VideoFrame> frame = std::get<0>(input); | 320 scoped_refptr<VideoFrame> frame = std::get<0>(input); |
325 | 321 |
326 uint8_t* buffer = NULL; | 322 uint8_t* buffer = NULL; |
327 size_t capacity = 0; | 323 size_t capacity = 0; |
328 status = media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity); | 324 status = media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity); |
329 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, "GetInputBuffer failed.", | 325 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, "GetInputBuffer failed.", |
330 kPlatformFailureError); | 326 kPlatformFailureError); |
331 | 327 |
332 size_t queued_size = | 328 size_t queued_size = |
333 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, frame->coded_size()); | 329 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, frame->coded_size()); |
334 RETURN_ON_FAILURE(capacity >= queued_size, | 330 RETURN_ON_FAILURE(capacity >= queued_size, |
335 "Failed to get input buffer: " << input_buf_index, | 331 "Failed to get input buffer: " << input_buf_index, |
336 kPlatformFailureError); | 332 kPlatformFailureError); |
337 | 333 |
338 uint8_t* dst_y = buffer; | 334 uint8_t* dst_y = buffer; |
339 int dst_stride_y = frame->stride(VideoFrame::kYPlane); | 335 int dst_stride_y = frame->stride(VideoFrame::kYPlane); |
340 uint8_t* dst_uv = | 336 uint8_t* dst_uv = |
341 buffer + | 337 buffer + |
342 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane); | 338 frame->stride(VideoFrame::kYPlane) * frame->rows(VideoFrame::kYPlane); |
343 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; | 339 int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; |
344 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other | 340 // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other |
345 // mention of that constant. | 341 // mention of that constant. |
346 bool converted = !libyuv::I420ToNV12( | 342 bool converted = !libyuv::I420ToNV12( |
347 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), | 343 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), |
348 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), | 344 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), |
349 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), | 345 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), |
350 dst_y, dst_stride_y, dst_uv, dst_stride_uv, frame->coded_size().width(), | 346 dst_y, dst_stride_y, dst_uv, dst_stride_uv, frame->coded_size().width(), |
351 frame->coded_size().height()); | 347 frame->coded_size().height()); |
352 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); | 348 RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); |
353 | 349 |
354 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); | 350 fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); |
355 status = media_codec_->QueueInputBuffer(input_buf_index, NULL, queued_size, | 351 status = media_codec_->QueueInputBuffer(input_buf_index, NULL, queued_size, |
356 fake_input_timestamp_); | 352 fake_input_timestamp_); |
357 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", | 353 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", |
358 base::Time::Now() - std::get<2>(input)); | 354 base::Time::Now() - std::get<2>(input)); |
359 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, | 355 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, |
360 "Failed to QueueInputBuffer: " << status, | 356 "Failed to QueueInputBuffer: " << status, |
361 kPlatformFailureError); | 357 kPlatformFailureError); |
362 ++num_buffers_at_codec_; | 358 ++num_buffers_at_codec_; |
363 pending_frames_.pop(); | 359 pending_frames_.pop(); |
364 } | 360 } |
365 | 361 |
366 void AndroidVideoEncodeAccelerator::DequeueOutput() { | 362 void AndroidVideoEncodeAccelerator::DequeueOutput() { |
367 if (!client_ptr_factory_->GetWeakPtr() || | 363 if (!client_ptr_factory_->GetWeakPtr() || |
368 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { | 364 available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { |
369 return; | 365 return; |
370 } | 366 } |
371 | 367 |
372 int32_t buf_index = 0; | 368 int32_t buf_index = 0; |
373 size_t offset = 0; | 369 size_t offset = 0; |
374 size_t size = 0; | 370 size_t size = 0; |
375 bool key_frame = false; | 371 bool key_frame = false; |
376 do { | 372 do { |
377 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 373 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
378 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); | 374 NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); |
379 switch (status) { | 375 switch (status) { |
380 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 376 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
381 return; | 377 return; |
382 | 378 |
383 case media::MEDIA_CODEC_ERROR: | 379 case MEDIA_CODEC_ERROR: |
384 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); | 380 RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); |
385 // Unreachable because of previous statement, but included for clarity. | 381 // Unreachable because of previous statement, but included for clarity. |
386 return; | 382 return; |
387 | 383 |
388 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 384 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
389 RETURN_ON_FAILURE(false, "Unexpected output format change", | 385 RETURN_ON_FAILURE(false, "Unexpected output format change", |
390 kPlatformFailureError); | 386 kPlatformFailureError); |
391 break; | 387 break; |
392 | 388 |
393 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 389 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
394 break; | 390 break; |
395 | 391 |
396 case media::MEDIA_CODEC_OK: | 392 case MEDIA_CODEC_OK: |
397 DCHECK_GE(buf_index, 0); | 393 DCHECK_GE(buf_index, 0); |
398 break; | 394 break; |
399 | 395 |
400 default: | 396 default: |
401 NOTREACHED(); | 397 NOTREACHED(); |
402 break; | 398 break; |
403 } | 399 } |
404 } while (buf_index < 0); | 400 } while (buf_index < 0); |
405 | 401 |
406 media::BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back(); | 402 BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back(); |
407 available_bitstream_buffers_.pop_back(); | 403 available_bitstream_buffers_.pop_back(); |
408 std::unique_ptr<SharedMemoryRegion> shm( | 404 std::unique_ptr<SharedMemoryRegion> shm( |
409 new SharedMemoryRegion(bitstream_buffer, false)); | 405 new SharedMemoryRegion(bitstream_buffer, false)); |
410 RETURN_ON_FAILURE(shm->Map(), "Failed to map SHM", kPlatformFailureError); | 406 RETURN_ON_FAILURE(shm->Map(), "Failed to map SHM", kPlatformFailureError); |
411 RETURN_ON_FAILURE(size <= shm->size(), | 407 RETURN_ON_FAILURE(size <= shm->size(), |
412 "Encoded buffer too large: " << size << ">" << shm->size(), | 408 "Encoded buffer too large: " << size << ">" << shm->size(), |
413 kPlatformFailureError); | 409 kPlatformFailureError); |
414 | 410 |
415 media::MediaCodecStatus status = media_codec_->CopyFromOutputBuffer( | 411 MediaCodecStatus status = media_codec_->CopyFromOutputBuffer( |
416 buf_index, offset, shm->memory(), size); | 412 buf_index, offset, shm->memory(), size); |
417 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, | 413 RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, "CopyFromOutputBuffer failed", |
418 "CopyFromOutputBuffer failed", kPlatformFailureError); | 414 kPlatformFailureError); |
419 media_codec_->ReleaseOutputBuffer(buf_index, false); | 415 media_codec_->ReleaseOutputBuffer(buf_index, false); |
420 --num_buffers_at_codec_; | 416 --num_buffers_at_codec_; |
421 | 417 |
422 base::ThreadTaskRunnerHandle::Get()->PostTask( | 418 base::ThreadTaskRunnerHandle::Get()->PostTask( |
423 FROM_HERE, | 419 FROM_HERE, |
424 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, | 420 base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, |
425 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, | 421 client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, |
426 key_frame, base::Time::Now() - base::Time())); | 422 key_frame, base::Time::Now() - base::Time())); |
427 } | 423 } |
428 | 424 |
429 } // namespace media | 425 } // namespace media |
OLD | NEW |