rtc_video_encoder.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/bitstream_buffer.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/video_frame.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "media/base/video_util.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/filters/gpu_video_accelerator_factories.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/video/video_encode_accelerator.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/webrtc/system_wrappers/interface/tick_util.h"
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#define NOTIFY_ERROR(x)                             \
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  do {                                              \
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "calling NotifyError(): " << x;  \
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NotifyError(x);                                 \
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } while (0)
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace content {
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This private class of RTCVideoEncoder does the actual work of communicating
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// with a media::VideoEncodeAccelerator for handling video encoding.  It can
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// be created on any thread, but should subsequently be posted to (and Destroy()
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// called on) a single thread.  Callbacks to RTCVideoEncoder are posted to the
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// thread on which the instance was constructed.
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This class separates state related to the thread that RTCVideoEncoder
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// operates on (presently the libjingle worker thread) from the thread that
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |gpu_factories_| provides for accelerator operations (presently the media
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// thread).  The RTCVideoEncoder class can be deleted directly by WebRTC, while
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA.
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class RTCVideoEncoder::Impl
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : public media::VideoEncodeAccelerator::Client,
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create the VEA and call Initialize() on it.  Called once per instantiation,
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // and then the instance is bound forevermore to whichever thread made the
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // call.
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder expects to be able to call this function synchronously from
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // its own thread, hence the |async_waiter| and |async_retval| arguments.
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void CreateAndInitializeVEA(const gfx::Size& input_visible_size,
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              uint32 bitrate,
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              media::VideoCodecProfile profile,
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              base::WaitableEvent* async_waiter,
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              int32_t* async_retval);
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Enqueue a frame from WebRTC for encoding.
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder expects to be able to call this function synchronously from
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // its own thread, hence the |async_waiter| and |async_retval| arguments.
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void Enqueue(const webrtc::I420VideoFrame* input_frame,
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               bool force_keyframe,
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               base::WaitableEvent* async_waiter,
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               int32_t* async_retval);
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder is given a buffer to be passed to WebRTC through the
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // RTCVideoEncoder::ReturnEncodedImage() function.  When that is complete,
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the buffer is returned to Impl by its index using this function.
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void UseOutputBitstreamBufferId(int32 bitstream_buffer_id);
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Request encoding parameter change for the underlying encoder.
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate);
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Destroy this Impl's encoder.  The destructor is not explicitly called, as
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Impl is a base::RefCountedThreadSafe.
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void Destroy();
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // media::VideoEncodeAccelerator::Client implementation.
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void NotifyInitializeDone() OVERRIDE;
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void RequireBitstreamBuffers(unsigned int input_count,
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       const gfx::Size& input_coded_size,
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       size_t output_buffer_size) OVERRIDE;
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    size_t payload_size,
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    bool key_frame) OVERRIDE;
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Impl>;
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  enum {
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    kInputBufferExtraCount = 1,  // The number of input buffers allocated, more
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 // than what is requested by
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 // VEA::RequireBitstreamBuffers().
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    kOutputBufferCount = 3,
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual ~Impl();
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Perform encoding on an input frame from the input queue.
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void EncodeOneFrame();
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Notify that an input frame is finished for encoding.  |index| is the index
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // of the completed frame in |input_buffers_|.
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void EncodeFrameFinished(int index);
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Set up/signal |async_waiter_| and |async_retval_|; see declarations below.
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void RegisterAsyncWaiter(base::WaitableEvent* waiter, int32_t* retval);
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void SignalAsyncWaiter(int32_t retval);
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::ThreadChecker thread_checker_;
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // notifications.
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The message loop on which to post callbacks to |weak_encoder_|.
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const scoped_refptr<base::MessageLoopProxy> encoder_message_loop_proxy_;
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Factory for creating VEAs, shared memory buffers, etc.
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous.
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Do this by waiting on the |async_waiter_| and returning the return value in
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |async_retval_| when initialization completes, encoding completes, or
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // an error occurs.
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent* async_waiter_;
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t* async_retval_;
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The underlying VEA to perform encoding on.
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<media::VideoEncodeAccelerator> video_encoder_;
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Next input frame.  Since there is at most one next frame, a single-element
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // queue is sufficient.
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const webrtc::I420VideoFrame* input_next_frame_;
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Whether to encode a keyframe next.
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool input_next_frame_keyframe_;
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Frame sizes.
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  gfx::Size input_frame_coded_size_;
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  gfx::Size input_visible_size_;
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Shared memory buffers for input/output with the VEA.
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedVector<base::SharedMemory> input_buffers_;
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedVector<base::SharedMemory> output_buffers_;
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Input buffers ready to be filled with input from Encode().  As a LIFO since
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // we don't care about ordering.
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<int> input_buffers_free_;
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The number of output buffers ready to be filled with output from the
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // encoder.
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int output_buffers_free_count_;
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Impl);
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::Impl::Impl(
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : weak_encoder_(weak_encoder),
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      encoder_message_loop_proxy_(base::MessageLoopProxy::current()),
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      gpu_factories_(gpu_factories),
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      async_waiter_(NULL),
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      async_retval_(NULL),
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      input_next_frame_(NULL),
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      input_next_frame_keyframe_(false),
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      output_buffers_free_count_(0) {
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  thread_checker_.DetachFromThread();
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const gfx::Size& input_visible_size,
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    uint32 bitrate,
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoCodecProfile profile,
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::WaitableEvent* async_waiter,
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int32_t* async_retval) {
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::CreateAndInitializeVEA()";
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RegisterAsyncWaiter(async_waiter, async_retval);
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitrate > kuint32max / 1000) {
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator().Pass();
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_) {
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_visible_size_ = input_visible_size;
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  video_encoder_->Initialize(media::VideoFrame::I420,
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             input_visible_size_,
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             profile,
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             bitrate * 1000,
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             this);
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::Enqueue(const webrtc::I420VideoFrame* input_frame,
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    bool force_keyframe,
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    base::WaitableEvent* async_waiter,
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    int32_t* async_retval) {
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::Enqueue()";
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!input_next_frame_);
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RegisterAsyncWaiter(async_waiter, async_retval);
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If there are no free input and output buffers, drop the frame to avoid a
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // deadlock. If there is a free input buffer, EncodeOneFrame will run and
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // unblock Encode(). If there are no free input buffers but there is a free
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // output buffer, EncodeFrameFinished will be called later to unblock
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Encode().
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The caller of Encode() holds a webrtc lock. The deadlock happens when:
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (1) Encode() is waiting for the frame to be encoded in EncodeOneFrame().
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (2) There are no free input buffers and they cannot be freed because
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     the encoder has no output buffers.
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (3) Output buffers cannot be freed because ReturnEncodedImage is queued
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     on libjingle worker thread to be run. But the worker thread is waiting
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //     for the same webrtc lock held by the caller of Encode().
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dropping a frame is fine. The encoder has been filled with all input
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // buffers. Returning an error in Encode() is not fatal and WebRTC will just
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // continue. If this is a key frame, WebRTC will request a key frame again.
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Besides, webrtc will drop a frame if Encode() blocks too long.
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (input_buffers_free_.empty() && output_buffers_free_count_ == 0) {
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(2) << "Run out of input and output buffers. Drop the frame.";
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_ = input_frame;
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_keyframe_ = force_keyframe;
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!input_buffers_free_.empty())
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EncodeOneFrame();
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int32 bitstream_buffer_id) {
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::UseOutputBitstreamBufferIndex(): "
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              "bitstream_buffer_id=" << bitstream_buffer_id;
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_) {
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        bitstream_buffer_id,
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        output_buffers_[bitstream_buffer_id]->handle(),
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        output_buffers_[bitstream_buffer_id]->mapped_size()));
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    output_buffers_free_count_++;
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RequestEncodingParametersChange(uint32 bitrate,
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                            uint32 framerate) {
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::RequestEncodingParametersChange(): bitrate=" << bitrate
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", framerate=" << framerate;
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitrate > kuint32max / 1000) {
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_)
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate);
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::Destroy() {
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::Destroy()";
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_)
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_.release()->Destroy();
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::NotifyInitializeDone() {
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::NotifyInitializeDone()";
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    unsigned int input_count,
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const gfx::Size& input_coded_size,
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    size_t output_buffer_size) {
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", input_coded_size=" << input_coded_size.ToString()
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", output_buffer_size=" << output_buffer_size;
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_)
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_frame_coded_size_ = input_coded_size;
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::SharedMemory* shm =
299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize(
300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            media::VideoFrame::I420, input_coded_size));
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!shm) {
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     "failed to create input buffer " << i;
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    input_buffers_.push_back(shm);
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    input_buffers_free_.push_back(i);
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < kOutputBufferCount; ++i) {
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::SharedMemory* shm =
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        gpu_factories_->CreateSharedMemory(output_buffer_size);
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!shm) {
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     "failed to create output buffer " << i;
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    output_buffers_.push_back(shm);
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Immediately provide all output buffers to the VEA.
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < output_buffers_.size(); ++i) {
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    output_buffers_free_count_++;
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::BitstreamBufferReady(int32 bitstream_buffer_id,
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 size_t payload_size,
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 bool key_frame) {
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::BitstreamBufferReady(): "
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              "bitstream_buffer_id=" << bitstream_buffer_id
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", payload_size=" << payload_size
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", key_frame=" << key_frame;
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (bitstream_buffer_id < 0 ||
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) {
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid bitstream_buffer_id="
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                << bitstream_buffer_id;
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id];
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (payload_size > output_buffer->mapped_size()) {
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid payload_size="
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                << payload_size;
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  output_buffers_free_count_--;
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Use webrtc timestamps to ensure correct RTP sender behavior.
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int64 capture_time_us = webrtc::TickTime::MicrosecondTimestamp();
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 capture_time_ms = capture_time_us / 1000;
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32_t rtp_timestamp = static_cast<uint32_t>(capture_time_us * 90 / 1000);
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      reinterpret_cast<uint8_t*>(output_buffer->memory()),
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      payload_size,
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      output_buffer->mapped_size()));
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_encodedWidth = input_visible_size_.width();
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_encodedHeight = input_visible_size_.height();
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  image->_timeStamp = rtp_timestamp;
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  image->capture_time_ms_ = capture_time_ms;
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  image->_completeFrame = true;
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encoder_message_loop_proxy_->PostTask(
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::ReturnEncodedImage,
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 weak_encoder_,
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 base::Passed(&image),
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 bitstream_buffer_id));
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::NotifyError(
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoEncodeAccelerator::Error error) {
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::NotifyError(): error=" << error;
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t retval;
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (error) {
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case media::VideoEncodeAccelerator::kInvalidArgumentError:
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      retval = WEBRTC_VIDEO_CODEC_ERROR;
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (video_encoder_)
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    video_encoder_.release()->Destroy();
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (async_waiter_) {
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SignalAsyncWaiter(retval);
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    encoder_message_loop_proxy_->PostTask(
4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        FROM_HERE,
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&RTCVideoEncoder::NotifyError, weak_encoder_, retval));
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); }
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::EncodeOneFrame() {
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::EncodeOneFrame()";
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(input_next_frame_);
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!input_buffers_free_.empty());
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // EncodeOneFrame() may re-enter EncodeFrameFinished() if VEA::Encode() fails,
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // we receive a VEA::NotifyError(), and the media::VideoFrame we pass to
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Encode() gets destroyed early.  Handle this by resetting our
4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // input_next_frame_* state before we hand off the VideoFrame to the VEA.
4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const webrtc::I420VideoFrame* next_frame = input_next_frame_;
4223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool next_frame_keyframe = input_next_frame_keyframe_;
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_ = NULL;
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_next_frame_keyframe_ = false;
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!video_encoder_) {
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int index = input_buffers_free_.back();
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::SharedMemory* input_buffer = input_buffers_[index];
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<media::VideoFrame> frame =
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      media::VideoFrame::WrapExternalPackedMemory(
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          media::VideoFrame::I420,
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_frame_coded_size_,
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          gfx::Rect(input_visible_size_),
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_visible_size_,
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          reinterpret_cast<uint8*>(input_buffer->memory()),
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          input_buffer->mapped_size(),
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          input_buffer->handle(),
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::TimeDelta(),
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index));
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!frame) {
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame";
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Do a strided copy of the input frame to match the input requirements for
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the encoder.
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(sheu): support zero-copy from WebRTC.  http://crbug.com/269312
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyYPlane(next_frame->buffer(webrtc::kYPlane),
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kYPlane),
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyUPlane(next_frame->buffer(webrtc::kUPlane),
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kUPlane),
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  media::CopyVPlane(next_frame->buffer(webrtc::kVPlane),
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->stride(webrtc::kVPlane),
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    next_frame->height(),
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    frame.get());
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  video_encoder_->Encode(frame, next_frame_keyframe);
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_buffers_free_.pop_back();
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) {
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index;
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GE(index, 0);
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_LT(index, static_cast<int>(input_buffers_.size()));
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  input_buffers_free_.push_back(index);
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (input_next_frame_)
4783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EncodeOneFrame();
4793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::RegisterAsyncWaiter(base::WaitableEvent* waiter,
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                int32_t* retval) {
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!async_waiter_);
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!async_retval_);
4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_ = waiter;
4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_retval_ = retval;
4883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::Impl::SignalAsyncWaiter(int32_t retval) {
4913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *async_retval_ = retval;
4933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_->Signal();
4943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_retval_ = NULL;
4953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  async_waiter_ = NULL;
4963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#undef NOTIFY_ERROR
4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
5023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// RTCVideoEncoder
5033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//
5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::RTCVideoEncoder(
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    webrtc::VideoCodecType type,
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoCodecProfile profile,
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : video_codec_type_(type),
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      video_codec_profile_(profile),
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      gpu_factories_(gpu_factories),
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      encoded_image_callback_(NULL),
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      weak_this_factory_(this) {
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RTCVideoEncoder::~RTCVideoEncoder() {
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Release();
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!impl_);
5233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    int32_t number_of_cores,
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    uint32_t max_payload_size) {
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", width=" << codec_settings->width
5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", height=" << codec_settings->height
5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", startBitrate=" << codec_settings->startBitrate;
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!impl_);
5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  weak_this_factory_.InvalidateWeakPtrs();
536424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  impl_ = new Impl(weak_this_factory_.GetWeakPtr(), gpu_factories_);
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent initialization_waiter(true, false);
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 gfx::Size(codec_settings->width, codec_settings->height),
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 codec_settings->startBitrate,
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 video_codec_profile_,
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &initialization_waiter,
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &initialization_retval));
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects this call to be synchronous.
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  initialization_waiter.Wait();
5518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  RecordInitEncodeUMA(initialization_retval);
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return initialization_retval;
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::Encode(
5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const webrtc::I420VideoFrame& input_image,
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const webrtc::CodecSpecificInfo* codec_specific_info,
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::vector<webrtc::VideoFrameType>* frame_types) {
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Encode()";
5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(sheu): figure out why this check fails.
5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // DCHECK(thread_checker_.CalledOnValidThread());
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!impl_) {
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WaitableEvent encode_waiter(true, false);
5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::Enqueue,
5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
5733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &input_image,
5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 (frame_types->front() == webrtc::kKeyFrame),
5753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &encode_waiter,
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 &encode_retval));
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // webrtc::VideoEncoder expects this call to be synchronous.
5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encode_waiter.Wait();
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval;
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return encode_retval;
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    webrtc::EncodedImageCallback* callback) {
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "RegisterEncodeCompleteCallback()";
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!impl_) {
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  encoded_image_callback_ = callback;
5943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::Release() {
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "Release()";
5993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (impl_) {
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_factories_->GetTaskRunner()->PostTask(
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
6043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    impl_ = NULL;
605424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    weak_this_factory_.InvalidateWeakPtrs();
6063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", rtt=" << rtt;
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Ignored.
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate
6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           << ", frame_rate=" << frame_rate;
6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!impl_) {
6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(3) << "SetRates(): returning " << impl_status_;
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return impl_status_;
6263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
6303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange,
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
6323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 new_bit_rate,
6333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 frame_rate));
6343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return WEBRTC_VIDEO_CODEC_OK;
6353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
6383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                         int32 bitstream_buffer_id) {
6393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(3) << "ReturnEncodedImage(): "
6413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              "bitstream_buffer_id=" << bitstream_buffer_id;
6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!encoded_image_callback_)
6443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
6453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  webrtc::CodecSpecificInfo info;
64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  memset(&info, 0, sizeof(info));
6483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  info.codecType = video_codec_type_;
64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (video_codec_type_ == webrtc::kVideoCodecVP8) {
65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info.codecSpecific.VP8.pictureId = -1;
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info.codecSpecific.VP8.tl0PicIdx = -1;
65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info.codecSpecific.VP8.keyIdx = -1;
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
6543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Generate a header describing a single fragment.
6563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  webrtc::RTPFragmentationHeader header;
65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  memset(&header, 0, sizeof(header));
6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  header.VerifyAndAllocateFragmentationHeader(1);
6593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  header.fragmentationOffset[0] = 0;
6603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  header.fragmentationLength[0] = image->_length;
6613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  header.fragmentationPlType[0] = 0;
6623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  header.fragmentationTimeDiff[0] = 0;
6633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
6653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (retval < 0) {
6663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
6673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             << retval;
6683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The call through webrtc::EncodedImageCallback is synchronous, so we can
6713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // immediately recycle the output buffer back to the Impl.
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
6733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
6743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 impl_,
6763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 bitstream_buffer_id));
6773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RTCVideoEncoder::NotifyError(int32_t error) {
6803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DVLOG(1) << "NotifyError(): error=" << error;
6823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  impl_status_ = error;
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gpu_factories_->GetTaskRunner()->PostTask(
6853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
6863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  impl_ = NULL;
6873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void RTCVideoEncoder::RecordInitEncodeUMA(int32_t init_retval) {
6908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
6918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        init_retval == WEBRTC_VIDEO_CODEC_OK);
6928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
6938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
6948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              video_codec_profile_,
695a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              media::VIDEO_CODEC_PROFILE_MAX + 1);
6968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
6978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace content
700