1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/gpu/media/android_video_encode_accelerator.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/metrics/histogram.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/gpu/gpu_channel.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/common/content_switches.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "media/base/android/media_codec_bridge.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "media/base/bitstream_buffer.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "media/base/limits.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "media/video/picture.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "third_party/libyuv/include/libyuv/convert_from.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/gl/android/scoped_java_surface.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using media::MediaCodecBridge; 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using media::VideoCodecBridge; 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using media::VideoFrame; 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace content { 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)enum { 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Subset of MediaCodecInfo.CodecCapabilities. 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) COLOR_FORMAT_YUV420_SEMIPLANAR = 21, 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Helper macros for dealing with failure. If |result| evaluates false, emit 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// |log| to DLOG(ERROR), register |error| with the client, and return. 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define RETURN_ON_FAILURE(result, log, error) \ 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) do { \ 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!(result)) { \ 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DLOG(ERROR) << log; \ 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (client_ptr_factory_.GetWeakPtr()) { \ 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.GetWeakPtr()->NotifyError(error); \ 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.InvalidateWeakPtrs(); \ 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } \ 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; \ 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } \ 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } while (0) 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Because MediaCodec is thread-hostile (must be poked on a single thread) and 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// has no callback mechanism (b/11990118), we must drive it by polling for 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// complete frames (and available input buffers, when the codec is fully 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// saturated). This function defines the polling delay. The value used is an 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// arbitrary choice that trades off CPU utilization (spinning) against latency. 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Mirrors android_video_decode_accelerator.cc::DecodePollDelay(). 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline const base::TimeDelta EncodePollDelay() { 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // An alternative to this polling scheme could be to dedicate a new thread 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // (instead of using the ChildThread) to run the MediaCodec, and make that 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // thread use the timeout-based flavor of MediaCodec's dequeue methods when it 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // believes the codec should complete "soon" (e.g. waiting for an input 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // buffer, or waiting for a picture when it knows enough complete input 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // pictures have been fed to saturate any internal buffering). This is 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // speculative and it's unclear that this would be a win (nor that there's a 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // reasonably device-agnostic way to fill in the "believes" above). 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return base::TimeDelta::FromMilliseconds(10); 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline const base::TimeDelta NoWaitTimeOut() { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return base::TimeDelta::FromMicroseconds(0); 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator( 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::VideoEncodeAccelerator::Client* client) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : client_ptr_factory_(client), 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) num_buffers_at_codec_(0), 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) num_output_buffers_(-1), 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) output_buffers_capacity_(0), 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) last_set_bitrate_(0) {} 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() { 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::vector<media::VideoEncodeAccelerator::SupportedProfile> 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AndroidVideoEncodeAccelerator::GetSupportedProfiles() { 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<MediaCodecBridge::CodecsInfo> codecs_info = 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MediaCodecBridge::GetCodecsInfo(); 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<SupportedProfile> profiles; 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return profiles; 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (size_t i = 0; i < codecs_info.size(); ++i) { 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const MediaCodecBridge::CodecsInfo& info = codecs_info[i]; 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (info.direction != media::MEDIA_CODEC_ENCODER || info.codecs != "vp8" || 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VideoCodecBridge::IsKnownUnaccelerated(media::kCodecVP8, 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::MEDIA_CODEC_ENCODER)) { 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We're only looking for a HW VP8 encoder. 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SupportedProfile profile; 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) profile.profile = media::VP8PROFILE_MAIN; 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Wouldn't it be nice if MediaCodec exposed the maximum capabilities of the 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // encoder? Sure would be. Too bad it doesn't. So we hard-code some 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // reasonable defaults. 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) profile.max_resolution.SetSize(1920, 1088); 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) profile.max_framerate.numerator = 30; 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) profile.max_framerate.denominator = 1; 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) profiles.push_back(profile); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return profiles; 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::Initialize( 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VideoFrame::Format format, 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::Size& input_visible_size, 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::VideoCodecProfile output_profile, 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 initial_bitrate) { 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", input_visible_size: " << input_visible_size.ToString() 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", output_profile: " << output_profile 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", initial_bitrate: " << initial_bitrate; 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!media_codec_); 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(media::MediaCodecBridge::IsAvailable() && 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::MediaCodecBridge::SupportsSetParameters() && 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) format == VideoFrame::I420 && 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) output_profile == media::VP8PROFILE_MAIN, 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Unexpected combo: " << format << ", " << output_profile, 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidArgumentError); 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) last_set_bitrate_ = initial_bitrate; 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only consider using MediaCodec if it's likely backed by hardware. 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(!media::VideoCodecBridge::IsKnownUnaccelerated( 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::kCodecVP8, media::MEDIA_CODEC_ENCODER), 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "No HW support", 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(fischman): when there is more HW out there with different color-space 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // support, this should turn into a negotiation with the codec for supported 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // formats. For now we use the only format supported by the only available 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // HW. 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_.reset( 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::VideoCodecBridge::CreateEncoder(media::kCodecVP8, 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) input_visible_size, 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) initial_bitrate, 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) INITIAL_FRAMERATE, 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) IFRAME_INTERVAL, 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) COLOR_FORMAT_YUV420_SEMIPLANAR)); 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE( 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_, 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Failed to create/start the codec: " << input_visible_size.ToString(), 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoop::current()->PostTask( 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&VideoEncodeAccelerator::Client::NotifyInitializeDone, 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.GetWeakPtr())); 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) num_output_buffers_ = media_codec_->GetOutputBuffersCount(); 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity(); 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoop::current()->PostTask( 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers, 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.GetWeakPtr(), 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) num_output_buffers_, 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) input_visible_size, 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) output_buffers_capacity_)); 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() { 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!io_timer_.IsRunning() && 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) { 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) io_timer_.Start(FROM_HERE, 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EncodePollDelay(), 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this, 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &AndroidVideoEncodeAccelerator::DoIOTask); 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() { 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (io_timer_.IsRunning() && 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (num_buffers_at_codec_ == 0 && pending_frames_.empty())) { 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) io_timer_.Stop(); 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::Encode( 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const scoped_refptr<VideoFrame>& frame, 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool force_keyframe) { 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe; 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(frame->format() == VideoFrame::I420, 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Unexpected format", 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidArgumentError); 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // MediaCodec doesn't have a way to specify stride for non-Packed formats, so 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // we insist on being called with packed frames and no cropping :( 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) == 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kYPlane) && 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->row_bytes(VideoFrame::kUPlane) == 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kUPlane) && 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->row_bytes(VideoFrame::kVPlane) == 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kVPlane) && 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Rect(frame->coded_size()) == frame->visible_rect(), 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Non-packed frame, or visible rect != coded size", 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidArgumentError); 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pending_frames_.push(MakeTuple(frame, force_keyframe, base::Time::Now())); 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DoIOTask(); 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer( 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const media::BitstreamBuffer& buffer) { 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id(); 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(buffer.size() >= media_codec_->GetOutputBuffersCapacity(), 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Output buffers too small!", 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidArgumentError); 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) available_bitstream_buffers_.push_back(buffer); 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DoIOTask(); 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange( 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 bitrate, 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 framerate) { 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", framerate: " << framerate; 233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (bitrate != last_set_bitrate_) { 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) last_set_bitrate_ = bitrate; 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->SetVideoBitrate(bitrate); 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Note: Android's MediaCodec doesn't allow mid-stream adjustments to 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // framerate, so we ignore that here. This is OK because Android only uses 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the framerate value from MediaFormat during configure() as a proxy for 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // bitrate, and we set that explicitly. 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::Destroy() { 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(3) << __PRETTY_FUNCTION__; 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.InvalidateWeakPtrs(); 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (media_codec_) { 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (io_timer_.IsRunning()) 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) io_timer_.Stop(); 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->Stop(); 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) delete this; 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::DoIOTask() { 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) QueueInput(); 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DequeueOutput(); 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MaybeStartIOTimer(); 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MaybeStopIOTimer(); 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::QueueInput() { 264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!client_ptr_factory_.GetWeakPtr() || pending_frames_.empty()) 265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int input_buf_index = 0; 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::MediaCodecStatus status = 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (status != media::MEDIA_CODEC_OK) { 271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status == media::MEDIA_CODEC_ERROR); 273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR, 274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "MediaCodec error", 275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const PendingFrames::value_type& input = pending_frames_.front(); 280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_key_frame = input.b; 281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (is_key_frame) { 282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could 283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // indicate this in the QueueInputBuffer() call below and guarantee _this_ 284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // frame be encoded as a key frame, but sadly that flag is ignored. 285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Instead, we request a key frame "soon". 286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->RequestKeyFrameSoon(); 287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<VideoFrame> frame = input.a; 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8* buffer = NULL; 291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t capacity = 0; 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity); 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t queued_size = 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VideoFrame::AllocationSize(VideoFrame::I420, frame->coded_size()); 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(capacity >= queued_size, 297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Failed to get input buffer: " << input_buf_index, 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8* dst_y = buffer; 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int dst_stride_y = frame->stride(VideoFrame::kYPlane); 302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8* dst_uv = buffer + frame->stride(VideoFrame::kYPlane) * 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->rows(VideoFrame::kYPlane); 304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2; 305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // mention of that constant. 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool converted = !libyuv::I420ToNV12(frame->data(VideoFrame::kYPlane), 308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kYPlane), 309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->data(VideoFrame::kUPlane), 310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kUPlane), 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->data(VideoFrame::kVPlane), 312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->stride(VideoFrame::kVPlane), 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dst_y, 314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dst_stride_y, 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dst_uv, 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dst_stride_uv, 317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->coded_size().width(), 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) frame->coded_size().height()); 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); 320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1); 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status = media_codec_->QueueInputBuffer( 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) input_buf_index, NULL, queued_size, fake_input_timestamp_); 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Media.AVEA.InputQueueTime", base::Time::Now() - input.c); 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Failed to QueueInputBuffer: " << status, 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++num_buffers_at_codec_; 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pending_frames_.pop(); 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool AndroidVideoEncodeAccelerator::DoOutputBuffersSuffice() { 333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If this returns false ever, then the VEA::Client interface will need to 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // grow a DismissBitstreamBuffer() call, and VEA::Client impls will have to be 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // prepared to field multiple requests to RequireBitstreamBuffers(). 336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int count = media_codec_->GetOutputBuffersCount(); 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t capacity = media_codec_->GetOutputBuffersCapacity(); 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool ret = media_codec_->GetOutputBuffers() && count <= num_output_buffers_ && 339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) capacity <= output_buffers_capacity_; 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: " 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_output_buffers_ << "x" << output_buffers_capacity_ 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", now: " << count << "x" << capacity; 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret); 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return ret; 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidVideoEncodeAccelerator::DequeueOutput() { 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!client_ptr_factory_.GetWeakPtr() || 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) { 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int32 buf_index = 0; 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t offset = 0; 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t size = 0; 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool key_frame = false; 357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) do { 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame); 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch (status) { 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case media::MEDIA_CODEC_ERROR: 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError); 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Unreachable because of previous statement, but included for clarity. 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: // Fall-through. 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(DoOutputBuffersSuffice(), 372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Bitstream now requires more/larger buffers", 373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case media::MEDIA_CODEC_OK: 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_GE(buf_index, 0); 378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } while (buf_index < 0); 385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back(); 387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) available_bitstream_buffers_.pop_back(); 388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<base::SharedMemory> shm( 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new base::SharedMemory(bitstream_buffer.handle(), false)); 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()), 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Failed to map SHM", 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RETURN_ON_FAILURE(size <= shm->mapped_size(), 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Encoded buffer too large: " << size << ">" 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << shm->mapped_size(), 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kPlatformFailureError); 397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->CopyFromOutputBuffer(buf_index, offset, shm->memory(), size); 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media_codec_->ReleaseOutputBuffer(buf_index, false); 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) --num_buffers_at_codec_; 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_10000("Media.AVEA.EncodedBufferSizeKB", size / 1024); 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoop::current()->PostTask( 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_ptr_factory_.GetWeakPtr(), 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bitstream_buffer.id(), 408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size, 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) key_frame)); 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace content 413