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 GpuVideoDecoderFactories; 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::GpuVideoDecoderFactories>& 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 114 // The meessage loop of |factories| will be saved to |vda_loop_proxy_|. 115 RTCVideoDecoder( 116 const scoped_refptr<media::GpuVideoDecoderFactories>& factories); 117 118 void Initialize(base::WaitableEvent* waiter); 119 120 // Requests a buffer to be decoded by VDA. 121 void RequestBufferDecode(); 122 123 bool CanMoreDecodeWorkBeDone(); 124 125 // Returns true if bitstream buffer id |id_buffer| comes after |id_reset|. 126 // This handles the wraparound. 127 bool IsBufferAfterReset(int32 id_buffer, int32 id_reset); 128 129 // Saves a WebRTC buffer in |decode_buffers_| for decode. 130 void SaveToDecodeBuffers_Locked(const webrtc::EncodedImage& input_image, 131 scoped_ptr<SHMBuffer> shm_buffer, 132 const BufferData& buffer_data); 133 134 // Saves a WebRTC buffer in |pending_buffers_| waiting for SHM available. 135 // Returns true on success. 136 bool SaveToPendingBuffers_Locked(const webrtc::EncodedImage& input_image, 137 const BufferData& buffer_data); 138 139 // Gets SHM and moves pending buffers to decode buffers. 140 void MovePendingBuffersToDecodeBuffers(); 141 142 scoped_refptr<media::VideoFrame> CreateVideoFrame( 143 const media::Picture& picture, 144 const media::PictureBuffer& pb, 145 uint32_t timestamp, 146 uint32_t width, 147 uint32_t height, 148 size_t size); 149 150 // Resets VDA. 151 void ResetInternal(); 152 153 // Tells VDA that a picture buffer can be recycled. 154 void ReusePictureBuffer(int64 picture_buffer_id, uint32 sync_point); 155 156 void DestroyTextures(); 157 void DestroyVDA(); 158 159 // Gets a shared-memory segment of at least |min_size| bytes from 160 // |available_shm_segments_|. Returns NULL if there is no buffer or the 161 // buffer is not big enough. 162 scoped_ptr<SHMBuffer> GetSHM_Locked(size_t min_size); 163 164 // Returns a shared-memory segment to the available pool. 165 void PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer); 166 167 // Allocates |number| shared memory of at least |min_size| bytes. 168 void CreateSHM(int number, size_t min_size); 169 170 // Stores the buffer metadata to |input_buffer_data_|. 171 void RecordBufferData(const BufferData& buffer_data); 172 // Gets the buffer metadata from |input_buffer_data_|. 173 void GetBufferData(int32 bitstream_buffer_id, 174 uint32_t* timestamp, 175 uint32_t* width, 176 uint32_t* height, 177 size_t* size); 178 179 enum State { 180 UNINITIALIZED, // The decoder has not initialized. 181 INITIALIZED, // The decoder has initialized. 182 RESETTING, // The decoder is being reset. 183 DECODE_ERROR, // Decoding error happened. 184 }; 185 186 static const int32 ID_LAST; // maximum bitstream buffer id 187 static const int32 ID_HALF; // half of the maximum bitstream buffer id 188 static const int32 ID_INVALID; // indicates Reset or Release never occurred 189 190 // The hardware video decoder. 191 scoped_ptr<media::VideoDecodeAccelerator> vda_; 192 193 // The size of the incoming video frames. 194 gfx::Size frame_size_; 195 196 // The weak pointer should live and die on the |vda_loop_proxy_|; 197 base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; 198 base::WeakPtr<RTCVideoDecoder> weak_this_; 199 200 scoped_refptr<media::GpuVideoDecoderFactories> factories_; 201 202 // The message loop to run callbacks on. This is from |factories_|. 203 scoped_refptr<base::MessageLoopProxy> vda_loop_proxy_; 204 205 // The texture target used for decoded pictures. 206 uint32 decoder_texture_target_; 207 208 // Metadata of the buffers that have been sent for decode. 209 std::list<BufferData> input_buffer_data_; 210 211 // A map from bitstream buffer IDs to bitstream buffers that are being 212 // processed by VDA. The map owns SHM buffers. 213 std::map<int32, SHMBuffer*> bitstream_buffers_in_decoder_; 214 215 // A map from picture buffer IDs to texture-backed picture buffers. 216 std::map<int32, media::PictureBuffer> assigned_picture_buffers_; 217 218 // Picture buffers that are dismissed but not deleted yet. 219 std::map<int32, media::PictureBuffer> dismissed_picture_buffers_; 220 221 // PictureBuffers given to us by VDA via PictureReady, which we sent forward 222 // as VideoFrames to be rendered via read_cb_, and which will be returned 223 // to us via ReusePictureBuffer. 224 std::set<int32> picture_buffers_at_display_; 225 226 // The id that will be given to the next picture buffer. 227 int32 next_picture_buffer_id_; 228 229 // Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|, 230 // |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|, 231 // |next_bitstream_buffer_id_| and |reset_bitstream_buffer_id_|. 232 base::Lock lock_; 233 234 // The state of RTCVideoDecoder. Guarded by |lock_|. 235 State state_; 236 237 // Guarded by |lock_|. 238 webrtc::DecodedImageCallback* decode_complete_callback_; 239 240 // Total number of allocated SHM buffers. Guarded by |lock_|. 241 int num_shm_buffers_; 242 243 // Shared-memory buffer pool. Since allocating SHM segments requires a 244 // round-trip to the browser process, we keep allocation out of the 245 // steady-state of the decoder. The vector owns SHM buffers. Guarded by 246 // |lock_|. 247 std::vector<SHMBuffer*> available_shm_segments_; 248 249 // A queue storing WebRTC encoding images (and their metadata) that are 250 // waiting for the shared memory. Guarded by |lock_|. 251 std::deque<std::pair<webrtc::EncodedImage, BufferData> > pending_buffers_; 252 253 // A queue storing buffers (and their metadata) that will be sent to VDA for 254 // decode. The queue owns SHM buffers. Guarded by |lock_|. 255 std::deque<std::pair<SHMBuffer*, BufferData> > decode_buffers_; 256 257 // The id that will be given to the next bitstream buffer. Guarded by |lock_|. 258 int32 next_bitstream_buffer_id_; 259 260 // A buffer that has an id less than this should be dropped because Reset or 261 // Release has been called. Guarded by |lock_|. 262 int32 reset_bitstream_buffer_id_; 263 264 DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder); 265 }; 266 267 } // namespace content 268 269 #endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_ 270