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