13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/renderer/media/rtc_video_encoder.h"
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/bind.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/location.h"
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/logging.h"
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/memory/scoped_vector.h"
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/metrics/histogram.h"
13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/rand_util.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/bitstream_buffer.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/video_frame.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "media/base/video_util.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/filters/gpu_video_accelerator_factories.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "media/filters/h264_parser.h"
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/video/video_encode_accelerator.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/webrtc/system_wrappers/interface/tick_util.h"
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#define NOTIFY_ERROR(x)                             \
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  do {                                              \
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "calling NotifyError(): " << x;  \
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NotifyError(x);                                 \
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } while (0)
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace content {
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Populates struct webrtc::RTPFragmentationHeader for H264 codec.
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Each entry specifies the offset and length (excluding start code) of a NALU.
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Returns true if successful.
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool GetRTPFragmentationHeaderH264(webrtc::RTPFragmentationHeader* header,
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                   const uint8_t* data, uint32_t length) {
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  media::H264Parser parser;
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  parser.SetStream(data, length);
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::vector<media::H264NALU> nalu_vector;
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  while (true) {
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    media::H264NALU nalu;
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const media::H264Parser::Result result = parser.AdvanceToNextNALU(&nalu);
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (result == media::H264Parser::kOk) {
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      nalu_vector.push_back(nalu);
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else if (result == media::H264Parser::kEOStream) {
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DLOG(ERROR) << "Unexpected H264 parser result";
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return false;
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  header->VerifyAndAllocateFragmentationHeader(nalu_vector.size());
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < nalu_vector.size(); ++i) {
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    header->fragmentationOffset[i] = nalu_vector[i].data - data;
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    header->fragmentationLength[i] = nalu_vector[i].size;
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    header->fragmentationPlType[i] = 0;
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    header->fragmentationTimeDiff[i] = 0;
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This private class of RTCVideoEncoder does the actual work of communicating
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// with a media::VideoEncodeAccelerator for handling video encoding.  It can
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// be created on any thread, but should subsequently be posted to (and Destroy()
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// called on) a single thread.  Callbacks to RTCVideoEncoder are posted to the
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// thread on which the instance was constructed.
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This class separates state related to the thread that RTCVideoEncoder
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// operates on (presently the libjingle worker thread) from the thread that
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |gpu_factories_| provides for accelerator operations (presently the media
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// thread).  The RTCVideoEncoder class can be deleted directly by WebRTC, while
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA.
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class RTCVideoEncoder::Impl
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : public media::VideoEncodeAccelerator::Client,
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create the VEA and call Initialize() on it.  Called once per instantiation,
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // and then the instance is bound forevermore to whichever thread made the
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // call.
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder expects to be able to call this function synchronously from
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // its own thread, hence the |async_waiter| and |async_retval| arguments.
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void CreateAndInitializeVEA(const gfx::Size& input_visible_size,
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              uint32 bitrate,
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              media::VideoCodecProfile profile,
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              base::WaitableEvent* async_waiter,
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              int32_t* async_retval);
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Enqueue a frame from WebRTC for encoding.
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder expects to be able to call this function synchronously from
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // its own thread, hence the |async_waiter| and |async_retval| arguments.
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void Enqueue(const webrtc::I420VideoFrame* input_frame,
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               bool force_keyframe,
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               base::WaitableEvent* async_waiter,
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               int32_t* async_retval);
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder is given a buffer to be passed to WebRTC through the
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder::ReturnEncodedImage() function.  When that is complete,
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the buffer is returned to Impl by its index using this function.
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void UseOutputBitstreamBufferId(int32 bitstream_buffer_id);
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Request encoding parameter change for the underlying encoder.
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate);
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Destroy this Impl's encoder.  The destructor is not explicitly called, as
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Impl is a base::RefCountedThreadSafe.
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void Destroy();
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // media::VideoEncodeAccelerator::Client implementation.
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void RequireBitstreamBuffers(unsigned int input_count,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       const gfx::Size& input_coded_size,
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       size_t output_buffer_size) OVERRIDE;
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    size_t payload_size,
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    bool key_frame) OVERRIDE;
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Impl>;
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  enum {
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    kInputBufferExtraCount = 1,  // The number of input buffers allocated, more
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 // than what is requested by
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 // VEA::RequireBitstreamBuffers().
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    kOutputBufferCount = 3,
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual ~Impl();
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Perform encoding on an input frame from the input queue.
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void EncodeOneFrame();
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Notify that an input frame is finished for encoding.  |index| is the index
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // of the completed frame in |input_buffers_|.
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void EncodeFrameFinished(int index);
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Set up/signal |async_waiter_| and |async_retval_|; see declarations below.
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void RegisterAsyncWaiter(base::WaitableEvent* waiter, int32_t* retval);
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void SignalAsyncWaiter(int32_t retval);
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::ThreadChecker thread_checker_;
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // notifications.
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The message loop on which to post callbacks to |weak_encoder_|.
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const scoped_refptr<base::MessageLoopProxy> encoder_message_loop_proxy_;
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Factory for creating VEAs, shared memory buffers, etc.
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous.
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Do this by waiting on the |async_waiter_| and returning the return value in
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |async_retval_| when initialization completes, encoding completes, or
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // an error occurs.
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent* async_waiter_;
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t* async_retval_;
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The underlying VEA to perform encoding on.
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<media::VideoEncodeAccelerator> video_encoder_;
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Next input frame.  Since there is at most one next frame, a single-element
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // queue is sufficient.
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const webrtc::I420VideoFrame* input_next_frame_;
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Whether to encode a keyframe next.
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool input_next_frame_keyframe_;
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Frame sizes.
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  gfx::Size input_frame_coded_size_;
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  gfx::Size input_visible_size_;
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Shared memory buffers for input/output with the VEA.
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedVector<base::SharedMemory> input_buffers_;
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedVector<base::SharedMemory> output_buffers_;
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Input buffers ready to be filled with input from Encode().  As a LIFO since
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // we don't care about ordering.
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<int> input_buffers_free_;
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The number of output buffers ready to be filled with output from the
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // encoder.
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int output_buffers_free_count_;
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // 15 bits running index of the VP8 frames. See VP8 RTP spec for details.
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  uint16 picture_id_;
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Impl);
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::Impl::Impl(
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : weak_encoder_(weak_encoder),
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      encoder_message_loop_proxy_(base::MessageLoopProxy::current()),
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      gpu_factories_(gpu_factories),
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      async_waiter_(NULL),
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      async_retval_(NULL),
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      input_next_frame_(NULL),
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      input_next_frame_keyframe_(false),
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      output_buffers_free_count_(0) {
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  thread_checker_.DetachFromThread();
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Picture ID should start on a random number.
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF));
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const gfx::Size& input_visible_size,
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    uint32 bitrate,
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoCodecProfile profile,
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::WaitableEvent* async_waiter,
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int32_t* async_retval) {
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::CreateAndInitializeVEA()";
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RegisterAsyncWaiter(async_waiter, async_retval);
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitrate > kuint32max / 1000) {
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator().Pass();
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_) {
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_visible_size_ = input_visible_size;
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!video_encoder_->Initialize(media::VideoFrame::I420,
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  input_visible_size_,
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  profile,
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  bitrate * 1000,
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  this)) {
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::Enqueue(const webrtc::I420VideoFrame* input_frame,
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    bool force_keyframe,
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    base::WaitableEvent* async_waiter,
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    int32_t* async_retval) {
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::Enqueue()";
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!input_next_frame_);
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RegisterAsyncWaiter(async_waiter, async_retval);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If there are no free input and output buffers, drop the frame to avoid a
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // deadlock. If there is a free input buffer, EncodeOneFrame will run and
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // unblock Encode(). If there are no free input buffers but there is a free
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // output buffer, EncodeFrameFinished will be called later to unblock
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Encode().
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The caller of Encode() holds a webrtc lock. The deadlock happens when:
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (1) Encode() is waiting for the frame to be encoded in EncodeOneFrame().
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (2) There are no free input buffers and they cannot be freed because
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     the encoder has no output buffers.
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (3) Output buffers cannot be freed because ReturnEncodedImage is queued
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     on libjingle worker thread to be run. But the worker thread is waiting
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     for the same webrtc lock held by the caller of Encode().
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dropping a frame is fine. The encoder has been filled with all input
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // buffers. Returning an error in Encode() is not fatal and WebRTC will just
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // continue. If this is a key frame, WebRTC will request a key frame again.
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Besides, webrtc will drop a frame if Encode() blocks too long.
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (input_buffers_free_.empty() && output_buffers_free_count_ == 0) {
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(2) << "Run out of input and output buffers. Drop the frame.";
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_ = input_frame;
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_keyframe_ = force_keyframe;
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!input_buffers_free_.empty())
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EncodeOneFrame();
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int32 bitstream_buffer_id) {
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::UseOutputBitstreamBufferIndex(): "
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              "bitstream_buffer_id=" << bitstream_buffer_id;
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_) {
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        bitstream_buffer_id,
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        output_buffers_[bitstream_buffer_id]->handle(),
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        output_buffers_[bitstream_buffer_id]->mapped_size()));
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    output_buffers_free_count_++;
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RequestEncodingParametersChange(uint32 bitrate,
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                            uint32 framerate) {
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::RequestEncodingParametersChange(): bitrate=" << bitrate
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", framerate=" << framerate;
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitrate > kuint32max / 1000) {
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_)
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate);
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::Destroy() {
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::Destroy()";
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  video_encoder_.reset();
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    unsigned int input_count,
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const gfx::Size& input_coded_size,
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t output_buffer_size) {
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", input_coded_size=" << input_coded_size.ToString()
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", output_buffer_size=" << output_buffer_size;
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_)
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_frame_coded_size_ = input_coded_size;
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::SharedMemory* shm =
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize(
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            media::VideoFrame::I420, input_coded_size));
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!shm) {
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     "failed to create input buffer " << i;
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    input_buffers_.push_back(shm);
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    input_buffers_free_.push_back(i);
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < kOutputBufferCount; ++i) {
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::SharedMemory* shm =
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        gpu_factories_->CreateSharedMemory(output_buffer_size);
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!shm) {
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     "failed to create output buffer " << i;
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    output_buffers_.push_back(shm);
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Immediately provide all output buffers to the VEA.
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < output_buffers_.size(); ++i) {
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    output_buffers_free_count_++;
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::BitstreamBufferReady(int32 bitstream_buffer_id,
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 size_t payload_size,
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 bool key_frame) {
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::BitstreamBufferReady(): "
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              "bitstream_buffer_id=" << bitstream_buffer_id
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", payload_size=" << payload_size
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", key_frame=" << key_frame;
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitstream_buffer_id < 0 ||
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) {
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid bitstream_buffer_id="
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                << bitstream_buffer_id;
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id];
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (payload_size > output_buffer->mapped_size()) {
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid payload_size="
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                << payload_size;
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  output_buffers_free_count_--;
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Use webrtc timestamps to ensure correct RTP sender behavior.
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int64 capture_time_us = webrtc::TickTime::MicrosecondTimestamp();
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 capture_time_ms = capture_time_us / 1000;
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32_t rtp_timestamp = static_cast<uint32_t>(capture_time_us * 90 / 1000);
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      reinterpret_cast<uint8_t*>(output_buffer->memory()),
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      payload_size,
4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      output_buffer->mapped_size()));
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_encodedWidth = input_visible_size_.width();
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_encodedHeight = input_visible_size_.height();
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  image->_timeStamp = rtp_timestamp;
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  image->capture_time_ms_ = capture_time_ms;
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_completeFrame = true;
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encoder_message_loop_proxy_->PostTask(
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::ReturnEncodedImage,
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 weak_encoder_,
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 base::Passed(&image),
420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 bitstream_buffer_id,
421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 picture_id_));
422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Picture ID must wrap after reaching the maximum.
423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  picture_id_ = (picture_id_ + 1) & 0x7FFF;
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::NotifyError(
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoEncodeAccelerator::Error error) {
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::NotifyError(): error=" << error;
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t retval;
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (error) {
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case media::VideoEncodeAccelerator::kInvalidArgumentError:
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      retval = WEBRTC_VIDEO_CODEC_ERROR;
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  video_encoder_.reset();
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (async_waiter_) {
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SignalAsyncWaiter(retval);
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    encoder_message_loop_proxy_->PostTask(
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        FROM_HERE,
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&RTCVideoEncoder::NotifyError, weak_encoder_, retval));
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); }
4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::EncodeOneFrame() {
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::EncodeOneFrame()";
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(input_next_frame_);
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!input_buffers_free_.empty());
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // EncodeOneFrame() may re-enter EncodeFrameFinished() if VEA::Encode() fails,
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // we receive a VEA::NotifyError(), and the media::VideoFrame we pass to
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Encode() gets destroyed early.  Handle this by resetting our
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // input_next_frame_* state before we hand off the VideoFrame to the VEA.
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const webrtc::I420VideoFrame* next_frame = input_next_frame_;
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool next_frame_keyframe = input_next_frame_keyframe_;
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_ = NULL;
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_keyframe_ = false;
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_) {
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int index = input_buffers_free_.back();
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::SharedMemory* input_buffer = input_buffers_[index];
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<media::VideoFrame> frame =
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      media::VideoFrame::WrapExternalPackedMemory(
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          media::VideoFrame::I420,
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_frame_coded_size_,
4783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          gfx::Rect(input_visible_size_),
4793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_visible_size_,
480424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          reinterpret_cast<uint8*>(input_buffer->memory()),
481424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          input_buffer->mapped_size(),
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_buffer->handle(),
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta(),
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index));
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!frame.get()) {
486424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame";
487424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Do a strided copy of the input frame to match the input requirements for
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the encoder.
493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(sheu): support zero-copy from WebRTC.  http://crbug.com/269312
494424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyYPlane(next_frame->buffer(webrtc::kYPlane),
495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kYPlane),
496424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
497424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
498424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyUPlane(next_frame->buffer(webrtc::kUPlane),
499424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kUPlane),
500424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
501424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
502424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyVPlane(next_frame->buffer(webrtc::kVPlane),
503424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kVPlane),
504424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
505424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  video_encoder_->Encode(frame, next_frame_keyframe);
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_buffers_free_.pop_back();
5093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) {
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index;
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GE(index, 0);
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_LT(index, static_cast<int>(input_buffers_.size()));
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_buffers_free_.push_back(index);
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (input_next_frame_)
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EncodeOneFrame();
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RegisterAsyncWaiter(base::WaitableEvent* waiter,
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                int32_t* retval) {
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!async_waiter_);
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!async_retval_);
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_ = waiter;
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_retval_ = retval;
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::SignalAsyncWaiter(int32_t retval) {
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *async_retval_ = retval;
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_->Signal();
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_retval_ = NULL;
5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_ = NULL;
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#undef NOTIFY_ERROR
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// RTCVideoEncoder
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::RTCVideoEncoder(
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    webrtc::VideoCodecType type,
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoCodecProfile profile,
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : video_codec_type_(type),
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      video_codec_profile_(profile),
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      gpu_factories_(gpu_factories),
5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      encoded_image_callback_(NULL),
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
55623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      weak_factory_(this) {
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::~RTCVideoEncoder() {
561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DVLOG(3) << "~RTCVideoEncoder";
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Release();
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!impl_.get());
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    int32_t number_of_cores,
5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    uint32_t max_payload_size) {
5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", width=" << codec_settings->width
5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", height=" << codec_settings->height
5733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", startBitrate=" << codec_settings->startBitrate;
5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!impl_.get());
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
57723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
57823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_);
5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent initialization_waiter(true, false);
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 gfx::Size(codec_settings->width, codec_settings->height),
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 codec_settings->startBitrate,
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 video_codec_profile_,
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &initialization_waiter,
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &initialization_retval));
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects this call to be synchronous.
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  initialization_waiter.Wait();
5938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  RecordInitEncodeUMA(initialization_retval);
5943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return initialization_retval;
5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::Encode(
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const webrtc::I420VideoFrame& input_image,
5993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const webrtc::CodecSpecificInfo* codec_specific_info,
6003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::vector<webrtc::VideoFrameType>* frame_types) {
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Encode()";
6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!impl_.get()) {
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
6043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
6053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
60723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool want_key_frame = frame_types && frame_types->size() &&
60823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                        frame_types->front() == webrtc::kKeyFrame;
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent encode_waiter(true, false);
6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::Enqueue,
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &input_image,
61623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 want_key_frame,
6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &encode_waiter,
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &encode_retval));
6193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects this call to be synchronous.
6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encode_waiter.Wait();
6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval;
6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return encode_retval;
6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    webrtc::EncodedImageCallback* callback) {
6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "RegisterEncodeCompleteCallback()";
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!impl_.get()) {
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
6323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
6333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encoded_image_callback_ = callback;
6363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::Release() {
6403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Release()";
6413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (impl_.get()) {
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_factories_->GetTaskRunner()->PostTask(
6453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
6463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    impl_ = NULL;
64723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    weak_factory_.InvalidateWeakPtrs();
6483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
6543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", rtt=" << rtt;
6563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Ignored.
6573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
6613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate
6623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", frame_rate=" << frame_rate;
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!impl_.get()) {
6643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "SetRates(): returning " << impl_status_;
6653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
6663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
6693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
6703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange,
6713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
6723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 new_bit_rate,
6733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 frame_rate));
6743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
678effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                         int32 bitstream_buffer_id,
679effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                         uint16 picture_id) {
6803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "ReturnEncodedImage(): "
682effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch           << "bitstream_buffer_id=" << bitstream_buffer_id
683effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch           << ", picture_id=" << picture_id;
6843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!encoded_image_callback_)
6863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
6873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
68803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  webrtc::RTPFragmentationHeader header;
68903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  memset(&header, 0, sizeof(header));
69003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  switch (video_codec_type_) {
69103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case webrtc::kVideoCodecVP8:
69203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case webrtc::kVideoCodecGeneric:
69303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // Generate a header describing a single fragment.
69403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // Note that webrtc treats the generic-type payload as an opaque buffer.
69503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      header.VerifyAndAllocateFragmentationHeader(1);
69603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      header.fragmentationOffset[0] = 0;
69703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      header.fragmentationLength[0] = image->_length;
69803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      header.fragmentationPlType[0] = 0;
69903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      header.fragmentationTimeDiff[0] = 0;
70003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
70103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case webrtc::kVideoCodecH264:
70203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (!GetRTPFragmentationHeaderH264(
70303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          &header, image->_buffer, image->_length)) {
70403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
70503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        NotifyError(WEBRTC_VIDEO_CODEC_ERROR);
70603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        return;
70703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      }
70803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
70903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    default:
71003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      NOTREACHED() << "Invalid video codec type";
71103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
71203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  webrtc::CodecSpecificInfo info;
71558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  memset(&info, 0, sizeof(info));
7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  info.codecType = video_codec_type_;
71768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (video_codec_type_ == webrtc::kVideoCodecVP8) {
718effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    info.codecSpecific.VP8.pictureId = picture_id;
71968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info.codecSpecific.VP8.tl0PicIdx = -1;
72068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info.codecSpecific.VP8.keyIdx = -1;
72168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
7223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
7243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (retval < 0) {
7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
7263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             << retval;
7273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The call through webrtc::EncodedImageCallback is synchronous, so we can
7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // immediately recycle the output buffer back to the Impl.
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 bitstream_buffer_id));
7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::NotifyError(int32_t error) {
7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
7403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "NotifyError(): error=" << error;
7413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  impl_status_ = error;
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
7443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  impl_ = NULL;
7463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void RTCVideoEncoder::RecordInitEncodeUMA(int32_t init_retval) {
7498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
7508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        init_retval == WEBRTC_VIDEO_CODEC_OK);
7518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
7528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
7538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              video_codec_profile_,
754a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              media::VIDEO_CODEC_PROFILE_MAX + 1);
7558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
7568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace content
759