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