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