summaryrefslogtreecommitdiffstats
path: root/media/filters/gpu_video_decoder.h
blob: eb82db67ca53aa76e9f026e6a156368c825c9ad6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_FILTERS_GPU_VIDEO_DECODER_H_
#define MEDIA_FILTERS_GPU_VIDEO_DECODER_H_

#include <stddef.h>
#include <stdint.h>

#include <list>
#include <map>
#include <set>
#include <utility>
#include <vector>

#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "media/base/pipeline_status.h"
#include "media/base/surface_manager.h"
#include "media/base/video_decoder.h"
#include "media/video/video_decode_accelerator.h"

template <class T> class scoped_refptr;

namespace base {
class SharedMemory;
class SingleThreadTaskRunner;
}

namespace gpu {
struct SyncToken;
}

namespace media {

class DecoderBuffer;
class GpuVideoAcceleratorFactories;
class MediaLog;

// GPU-accelerated video decoder implementation.  Relies on
// AcceleratedVideoDecoderMsg_Decode and friends.  Can be created on any thread
// but must be accessed and destroyed on GpuVideoAcceleratorFactories's
// GetMessageLoop().
class MEDIA_EXPORT GpuVideoDecoder
    : public VideoDecoder,
      public VideoDecodeAccelerator::Client {
 public:
  explicit GpuVideoDecoder(GpuVideoAcceleratorFactories* factories,
                           const RequestSurfaceCB& request_surface_cb);

  // VideoDecoder implementation.
  std::string GetDisplayName() const override;
  void Initialize(const VideoDecoderConfig& config,
                  bool low_delay,
                  CdmContext* cdm_context,
                  const InitCB& init_cb,
                  const OutputCB& output_cb) override;
  void CompleteInitialization(int cdm_id, int surface_id);
  void Decode(const scoped_refptr<DecoderBuffer>& buffer,
              const DecodeCB& decode_cb) override;
  void Reset(const base::Closure& closure) override;
  bool NeedsBitstreamConversion() const override;
  bool CanReadWithoutStalling() const override;
  int GetMaxDecodeRequests() const override;

  // VideoDecodeAccelerator::Client implementation.
  void NotifyCdmAttached(bool success) override;
  void ProvidePictureBuffers(uint32_t count,
                             const gfx::Size& size,
                             uint32_t texture_target) override;
  void DismissPictureBuffer(int32_t id) override;
  void PictureReady(const media::Picture& picture) override;
  void NotifyEndOfBitstreamBuffer(int32_t id) override;
  void NotifyFlushDone() override;
  void NotifyResetDone() override;
  void NotifyError(media::VideoDecodeAccelerator::Error error) override;

  static const char kDecoderName[];

 protected:
  ~GpuVideoDecoder() override;

 private:
  enum State {
    kNormal,
    kDrainingDecoder,
    kDecoderDrained,
    kError
  };

  // A shared memory segment and its allocated size.
  struct SHMBuffer {
    SHMBuffer(scoped_ptr<base::SharedMemory> m, size_t s);
    ~SHMBuffer();
    scoped_ptr<base::SharedMemory> shm;
    size_t size;
  };

  // A SHMBuffer and the DecoderBuffer its data came from.
  struct PendingDecoderBuffer {
    PendingDecoderBuffer(SHMBuffer* s,
                        const scoped_refptr<DecoderBuffer>& b,
                        const DecodeCB& done_cb);
    ~PendingDecoderBuffer();
    SHMBuffer* shm_buffer;
    scoped_refptr<DecoderBuffer> buffer;
    DecodeCB done_cb;
  };

  typedef std::map<int32_t, PictureBuffer> PictureBufferMap;

  void DeliverFrame(const scoped_refptr<VideoFrame>& frame);

  // Static method is to allow it to run even after GVD is deleted.
  static void ReleaseMailbox(base::WeakPtr<GpuVideoDecoder> decoder,
                             media::GpuVideoAcceleratorFactories* factories,
                             int64_t picture_buffer_id,
                             uint32_t texture_id,
                             const gpu::SyncToken& release_sync_token);
  // Indicate the picture buffer can be reused by the decoder.
  void ReusePictureBuffer(int64_t picture_buffer_id);

  void RecordBufferData(
      const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer);
  void GetBufferData(int32_t id,
                     base::TimeDelta* timetamp,
                     gfx::Rect* visible_rect,
                     gfx::Size* natural_size);

  void DestroyVDA();

  // Request a shared-memory segment of at least |min_size| bytes.  Will
  // allocate as necessary.
  scoped_ptr<SHMBuffer> GetSHM(size_t min_size);

  // Return a shared-memory segment to the available pool.
  void PutSHM(scoped_ptr<SHMBuffer> shm_buffer);

  // Destroy all PictureBuffers in |buffers|, and delete their textures.
  void DestroyPictureBuffers(PictureBufferMap* buffers);

  // Returns true if the video decoder with |capabilities| can support
  // |profile| and |coded_size|.
  bool IsProfileSupported(
      const VideoDecodeAccelerator::Capabilities& capabilities,
      VideoCodecProfile profile,
      const gfx::Size& coded_size);

  // Assert the contract that this class is operated on the right thread.
  void DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() const;

  bool needs_bitstream_conversion_;

  GpuVideoAcceleratorFactories* factories_;

  // Populated during Initialize() (on success) and unchanged until an error
  // occurs.
  scoped_ptr<VideoDecodeAccelerator> vda_;

  InitCB init_cb_;
  OutputCB output_cb_;

  DecodeCB eos_decode_cb_;

  // Not null only during reset.
  base::Closure pending_reset_cb_;

  State state_;

  VideoDecoderConfig config_;

  // For requesting a suface to render to. If this is null the VDA will return
  // normal video frames and not render them to a surface.
  RequestSurfaceCB request_surface_cb_;

  // Shared-memory buffer pool.  Since allocating SHM segments requires a
  // round-trip to the browser process, we keep allocation out of the
  // steady-state of the decoder.
  std::vector<SHMBuffer*> available_shm_segments_;

  std::map<int32_t, PendingDecoderBuffer> bitstream_buffers_in_decoder_;
  PictureBufferMap assigned_picture_buffers_;
  // PictureBuffers given to us by VDA via PictureReady, which we sent forward
  // as VideoFrames to be rendered via decode_cb_, and which will be returned
  // to us via ReusePictureBuffer.
  typedef std::map<int32_t /* picture_buffer_id */, uint32_t /* texture_id */>
      PictureBufferTextureMap;
  PictureBufferTextureMap picture_buffers_at_display_;

  // The texture target used for decoded pictures.
  uint32_t decoder_texture_target_;

  struct BufferData {
    BufferData(int32_t bbid,
               base::TimeDelta ts,
               const gfx::Rect& visible_rect,
               const gfx::Size& natural_size);
    ~BufferData();
    int32_t bitstream_buffer_id;
    base::TimeDelta timestamp;
    gfx::Rect visible_rect;
    gfx::Size natural_size;
  };
  std::list<BufferData> input_buffer_data_;

  // picture_buffer_id and the frame wrapping the corresponding Picture, for
  // frames that have been decoded but haven't been requested by a Decode() yet.
  int32_t next_picture_buffer_id_;
  int32_t next_bitstream_buffer_id_;

  // Set during ProvidePictureBuffers(), used for checking and implementing
  // HasAvailableOutputFrames().
  int available_pictures_;

  // If true, the client cannot expect the VDA to produce any new decoded
  // frames, until it returns all PictureBuffers it may be holding back to the
  // VDA. In other words, the VDA may require all PictureBuffers to be able to
  // proceed with decoding the next frame.
  bool needs_all_picture_buffers_to_decode_;

  // Bound to factories_->GetMessageLoop().
  // NOTE: Weak pointers must be invalidated before all other member variables.
  base::WeakPtrFactory<GpuVideoDecoder> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder);
};

}  // namespace media

#endif  // MEDIA_FILTERS_GPU_VIDEO_DECODER_H_