1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_ 6 #define CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_ 7 8 #include <deque> 9 #include <map> 10 #include <set> 11 #include <utility> 12 13 #include "base/basictypes.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/message_loop/message_loop.h" 17 #include "base/synchronization/lock.h" 18 #include "base/synchronization/waitable_event.h" 19 #include "base/threading/thread.h" 20 #include "content/common/content_export.h" 21 #include "media/base/bitstream_buffer.h" 22 #include "media/base/video_decoder.h" 23 #include "media/video/picture.h" 24 #include "media/video/video_decode_accelerator.h" 25 #include "third_party/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" 26 27 namespace base { 28 class MessageLoopProxy; 29 }; 30 31 namespace media { 32 class DecoderBuffer; 33 class GpuVideoAcceleratorFactories; 34 } 35 36 namespace content { 37 38 // This class uses hardware accelerated video decoder to decode video for 39 // WebRTC. |vda_message_loop_| is the message loop proxy of the media thread, 40 // which VDA::Client methods run on. webrtc::VideoDecoder methods run on WebRTC 41 // DecodingThread or Chrome_libJingle_WorkerThread, which are trampolined to 42 // |vda_message_loop_|. Decode() is non-blocking and queues the buffers. Decoded 43 // frames are delivered to WebRTC on |vda_message_loop_|. 44 class CONTENT_EXPORT RTCVideoDecoder 45 : NON_EXPORTED_BASE(public webrtc::VideoDecoder), 46 public media::VideoDecodeAccelerator::Client, 47 public base::MessageLoop::DestructionObserver { 48 public: 49 virtual ~RTCVideoDecoder(); 50 51 // Creates a RTCVideoDecoder. Returns NULL if failed. The video decoder will 52 // run on the message loop of |factories|. 53 static scoped_ptr<RTCVideoDecoder> Create( 54 webrtc::VideoCodecType type, 55 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories); 56 57 // webrtc::VideoDecoder implementation. 58 // Called on WebRTC DecodingThread. 59 virtual int32_t InitDecode(const webrtc::VideoCodec* codecSettings, 60 int32_t numberOfCores) OVERRIDE; 61 // Called on WebRTC DecodingThread. 62 virtual int32_t Decode( 63 const webrtc::EncodedImage& inputImage, 64 bool missingFrames, 65 const webrtc::RTPFragmentationHeader* fragmentation, 66 const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, 67 int64_t renderTimeMs = -1) OVERRIDE; 68 // Called on WebRTC DecodingThread. 69 virtual int32_t RegisterDecodeCompleteCallback( 70 webrtc::DecodedImageCallback* callback) OVERRIDE; 71 // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while 72 // this runs. 73 virtual int32_t Release() OVERRIDE; 74 // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while 75 // this runs. 76 virtual int32_t Reset() OVERRIDE; 77 78 // VideoDecodeAccelerator::Client implementation. 79 virtual void NotifyInitializeDone() OVERRIDE; 80 virtual void ProvidePictureBuffers(uint32 count, 81 const gfx::Size& size, 82 uint32 texture_target) OVERRIDE; 83 virtual void DismissPictureBuffer(int32 id) OVERRIDE; 84 virtual void PictureReady(const media::Picture& picture) OVERRIDE; 85 virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE; 86 virtual void NotifyFlushDone() OVERRIDE; 87 virtual void NotifyResetDone() OVERRIDE; 88 virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE; 89 90 // base::DestructionObserver implementation. Called when |vda_message_loop_| 91 // is stopped. 92 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 93 94 private: 95 class SHMBuffer; 96 // Metadata of a bitstream buffer. 97 struct BufferData { 98 BufferData(int32 bitstream_buffer_id, 99 uint32_t timestamp, 100 int width, 101 int height, 102 size_t size); 103 BufferData(); 104 ~BufferData(); 105 int32 bitstream_buffer_id; 106 uint32_t timestamp; // in 90KHz 107 uint32_t width; 108 uint32_t height; 109 size_t size; // buffer size 110 }; 111 112 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsBufferAfterReset); 113 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset); 114 115 // The meessage loop of |factories| will be saved to |vda_loop_proxy_|. 116 RTCVideoDecoder( 117 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories); 118 119 void Initialize(base::WaitableEvent* waiter); 120 121 // Requests a buffer to be decoded by VDA. 122 void RequestBufferDecode(); 123 124 bool CanMoreDecodeWorkBeDone(); 125 126 // Returns true if bitstream buffer id |id_buffer| comes after |id_reset|. 127 // This handles the wraparound. 128 bool IsBufferAfterReset(int32 id_buffer, int32 id_reset); 129 130 // Returns true if bitstream buffer |id_buffer| is the first buffer after 131 // |id_reset|. 132 bool IsFirstBufferAfterReset(int32 id_buffer, int32 id_reset); 133 134 // Saves a WebRTC buffer in |decode_buffers_| for decode. 135 void SaveToDecodeBuffers_Locked(const webrtc::EncodedImage& input_image, 136 scoped_ptr<SHMBuffer> shm_buffer, 137 const BufferData& buffer_data); 138 139 // Saves a WebRTC buffer in |pending_buffers_| waiting for SHM available. 140 // Returns true on success. 141 bool SaveToPendingBuffers_Locked(const webrtc::EncodedImage& input_image, 142 const BufferData& buffer_data); 143 144 // Gets SHM and moves pending buffers to decode buffers. 145 void MovePendingBuffersToDecodeBuffers(); 146 147 scoped_refptr<media::VideoFrame> CreateVideoFrame( 148 const media::Picture& picture, 149 const media::PictureBuffer& pb, 150 uint32_t timestamp, 151 uint32_t width, 152 uint32_t height, 153 size_t size); 154 155 // Resets VDA. 156 void ResetInternal(); 157 158 // Tells VDA that a picture buffer can be recycled. 159 void ReusePictureBuffer(int64 picture_buffer_id, uint32 sync_point); 160 161 void DestroyTextures(); 162 void DestroyVDA(); 163 164 // Gets a shared-memory segment of at least |min_size| bytes from 165 // |available_shm_segments_|. Returns NULL if there is no buffer or the 166 // buffer is not big enough. 167 scoped_ptr<SHMBuffer> GetSHM_Locked(size_t min_size); 168 169 // Returns a shared-memory segment to the available pool. 170 void PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer); 171 172 // Allocates |number| shared memory of at least |min_size| bytes. 173 void CreateSHM(int number, size_t min_size); 174 175 // Stores the buffer metadata to |input_buffer_data_|. 176 void RecordBufferData(const BufferData& buffer_data); 177 // Gets the buffer metadata from |input_buffer_data_|. 178 void GetBufferData(int32 bitstream_buffer_id, 179 uint32_t* timestamp, 180 uint32_t* width, 181 uint32_t* height, 182 size_t* size); 183 184 // Records the result of InitDecode to UMA and returns |status|. 185 int32_t RecordInitDecodeUMA(int32_t status); 186 187 enum State { 188 UNINITIALIZED, // The decoder has not initialized. 189 INITIALIZED, // The decoder has initialized. 190 RESETTING, // The decoder is being reset. 191 DECODE_ERROR, // Decoding error happened. 192 }; 193 194 static const int32 ID_LAST; // maximum bitstream buffer id 195 static const int32 ID_HALF; // half of the maximum bitstream buffer id 196 static const int32 ID_INVALID; // indicates Reset or Release never occurred 197 198 // The hardware video decoder. 199 scoped_ptr<media::VideoDecodeAccelerator> vda_; 200 201 // The size of the incoming video frames. 202 gfx::Size frame_size_; 203 204 // Weak pointer to this, which can be dereferenced only on |vda_loop_proxy_|. 205 base::WeakPtr<RTCVideoDecoder> weak_this_; 206 207 scoped_refptr<media::GpuVideoAcceleratorFactories> factories_; 208 209 // The message loop to run callbacks on. This is from |factories_|. 210 scoped_refptr<base::MessageLoopProxy> vda_loop_proxy_; 211 212 // The texture target used for decoded pictures. 213 uint32 decoder_texture_target_; 214 215 // Metadata of the buffers that have been sent for decode. 216 std::list<BufferData> input_buffer_data_; 217 218 // A map from bitstream buffer IDs to bitstream buffers that are being 219 // processed by VDA. The map owns SHM buffers. 220 std::map<int32, SHMBuffer*> bitstream_buffers_in_decoder_; 221 222 // A map from picture buffer IDs to texture-backed picture buffers. 223 std::map<int32, media::PictureBuffer> assigned_picture_buffers_; 224 225 // Picture buffers that are dismissed but not deleted yet. 226 std::map<int32, media::PictureBuffer> dismissed_picture_buffers_; 227 228 // PictureBuffers given to us by VDA via PictureReady, which we sent forward 229 // as VideoFrames to be rendered via read_cb_, and which will be returned 230 // to us via ReusePictureBuffer. 231 std::set<int32> picture_buffers_at_display_; 232 233 // The id that will be given to the next picture buffer. 234 int32 next_picture_buffer_id_; 235 236 // Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|, 237 // |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|, 238 // |next_bitstream_buffer_id_| and |reset_bitstream_buffer_id_|. 239 base::Lock lock_; 240 241 // The state of RTCVideoDecoder. Guarded by |lock_|. 242 State state_; 243 244 // Guarded by |lock_|. 245 webrtc::DecodedImageCallback* decode_complete_callback_; 246 247 // Total number of allocated SHM buffers. Guarded by |lock_|. 248 int num_shm_buffers_; 249 250 // Shared-memory buffer pool. Since allocating SHM segments requires a 251 // round-trip to the browser process, we keep allocation out of the 252 // steady-state of the decoder. The vector owns SHM buffers. Guarded by 253 // |lock_|. 254 std::vector<SHMBuffer*> available_shm_segments_; 255 256 // A queue storing WebRTC encoding images (and their metadata) that are 257 // waiting for the shared memory. Guarded by |lock_|. 258 std::deque<std::pair<webrtc::EncodedImage, BufferData> > pending_buffers_; 259 260 // A queue storing buffers (and their metadata) that will be sent to VDA for 261 // decode. The queue owns SHM buffers. Guarded by |lock_|. 262 std::deque<std::pair<SHMBuffer*, BufferData> > decode_buffers_; 263 264 // The id that will be given to the next bitstream buffer. Guarded by |lock_|. 265 int32 next_bitstream_buffer_id_; 266 267 // A buffer that has an id less than this should be dropped because Reset or 268 // Release has been called. Guarded by |lock_|. 269 int32 reset_bitstream_buffer_id_; 270 271 // Factory used to populate |weak_this_|. Must be destroyed, or invalidated, 272 // on |vda_loop_proxy_|. 273 base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; 274 275 DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder); 276 }; 277 278 } // namespace content 279 280 #endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_ 281