summaryrefslogtreecommitdiff
path: root/chromium/media/filters/gpu_video_decoder.h
blob: 29c330d2141ab0adb4916ec14825cf88082ffa50 (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
// 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 MessageLoopProxy;
class SharedMemory;
}

namespace media {

class DecoderBuffer;
class GpuVideoDecoderFactories;

// GPU-accelerated video decoder implementation.  Relies on
// AcceleratedVideoDecoderMsg_Decode and friends.
class MEDIA_EXPORT GpuVideoDecoder
    : public VideoDecoder,
      public VideoDecodeAccelerator::Client {
 public:
  // The message loop of |factories| will be saved to |gvd_loop_proxy_|.
  explicit GpuVideoDecoder(
      const scoped_refptr<GpuVideoDecoderFactories>& factories);

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

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

  // Indicate the picture buffer can be reused by the decoder.
  void ReusePictureBuffer(int64 picture_buffer_id, uint32 sync_point);

  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();

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

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

  void DestroyTextures();

  bool needs_bitstream_conversion_;

  // Message loop which this class and |factories_| run on.
  scoped_refptr<base::MessageLoopProxy> gvd_loop_proxy_;
  base::WeakPtrFactory<GpuVideoDecoder> weak_factory_;
  base::WeakPtr<GpuVideoDecoder> weak_this_;

  scoped_refptr<GpuVideoDecoderFactories> 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_;

  // Book-keeping variables.
  struct BufferPair {
    BufferPair(SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b);
    ~BufferPair();
    SHMBuffer* shm_buffer;
    scoped_refptr<DecoderBuffer> buffer;
  };
  std::map<int32, BufferPair> bitstream_buffers_in_decoder_;
  std::map<int32, PictureBuffer> assigned_picture_buffers_;
  std::map<int32, PictureBuffer> dismissed_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.
  std::set<int32> 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_;

  DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder);
};

}  // namespace media

#endif  // MEDIA_FILTERS_GPU_VIDEO_DECODER_H_