summaryrefslogtreecommitdiff
path: root/media/filters/gpu_video_decoder.h
blob: 6e05f63c5079a4abda2c84d26c14e5fc5a822942 (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
// 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 <list>
#include <map>
#include <set>
#include <utility>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "media/base/pipeline_status.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 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(
      const scoped_refptr<GpuVideoAcceleratorFactories>& factories,
      const scoped_refptr<MediaLog>& media_log);

  // VideoDecoder implementation.
  virtual void Initialize(const VideoDecoderConfig& config,
                          const PipelineStatusCB& status_cb) OVERRIDE;
  virtual void Decode(const scoped_refptr<DecoderBuffer>& buffer,
                      const DecodeCB& decode_cb) OVERRIDE;
  virtual void Reset(const base::Closure& closure) OVERRIDE;
  virtual void Stop(const base::Closure& closure) OVERRIDE;
  virtual bool HasAlpha() const OVERRIDE;
  virtual bool NeedsBitstreamConversion() const OVERRIDE;
  virtual bool CanReadWithoutStalling() const OVERRIDE;

  // VideoDecodeAccelerator::Client implementation.
  virtual void NotifyInitializeDone() OVERRIDE;
  virtual void ProvidePictureBuffers(uint32 count,
                                     const gfx::Size& size,
                                     uint32 texture_target) OVERRIDE;
  virtual void DismissPictureBuffer(int32 id) OVERRIDE;
  virtual void PictureReady(const media::Picture& picture) OVERRIDE;
  virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE;
  virtual void NotifyFlushDone() OVERRIDE;
  virtual void NotifyResetDone() OVERRIDE;
  virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;

 protected:
  virtual ~GpuVideoDecoder();

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

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

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

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

  // Return true if more decode work can be piled on to the VDA.
  bool CanMoreDecodeWorkBeDone();

  // Enqueue a frame for later delivery (or drop it on the floor if a
  // vda->Reset() is in progress) and trigger out-of-line delivery of the oldest
  // ready frame to the client if there is a pending read.  A NULL |frame|
  // merely triggers delivery, and requires the ready_video_frames_ queue not be
  // empty.
  void EnqueueFrameAndTriggerFrameDelivery(
      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,
      const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
      int64 picture_buffer_id,
      uint32 texture_id,
      scoped_ptr<gpu::MailboxHolder> mailbox_holder);
  // Indicate the picture buffer can be reused by the decoder.
  void ReusePictureBuffer(int64 picture_buffer_id);

  void RecordBufferData(
      const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer);
  void GetBufferData(int32 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.  Caller does not own returned pointer.
  SHMBuffer* GetSHM(size_t min_size);

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

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

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

  bool needs_bitstream_conversion_;

  scoped_refptr<GpuVideoAcceleratorFactories> factories_;

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

  // Callbacks that are !is_null() only during their respective operation being
  // asynchronously executed.
  DecodeCB pending_decode_cb_;
  base::Closure pending_reset_cb_;

  State state_;

  VideoDecoderConfig config_;

  // 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_;

  scoped_refptr<MediaLog> media_log_;

  std::map<int32, BufferPair> 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 /* picture_buffer_id */, uint32 /* texture_id */>
      PictureBufferTextureMap;
  PictureBufferTextureMap picture_buffers_at_display_;

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

  struct BufferData {
    BufferData(int32 bbid, base::TimeDelta ts, const gfx::Rect& visible_rect,
               const gfx::Size& natural_size);
    ~BufferData();
    int32 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.
  std::list<scoped_refptr<VideoFrame> > ready_video_frames_;
  int32 next_picture_buffer_id_;
  int32 next_bitstream_buffer_id_;

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

  // 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_