Home | History | Annotate | Download | only in media
      1 // Copyright 2014 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_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
      6 #define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include <map>
     11 #include <queue>
     12 
     13 #include "base/mac/scoped_cftyperef.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "base/message_loop/message_loop.h"
     17 #include "base/threading/thread.h"
     18 #include "content/common/gpu/media/vt.h"
     19 #include "media/filters/h264_parser.h"
     20 #include "media/video/video_decode_accelerator.h"
     21 #include "ui/gfx/geometry/size.h"
     22 #include "ui/gl/gl_context_cgl.h"
     23 
     24 namespace base {
     25 class SingleThreadTaskRunner;
     26 }  // namespace base
     27 
     28 namespace content {
     29 
     30 // VideoToolbox.framework implementation of the VideoDecodeAccelerator
     31 // interface for Mac OS X (currently limited to 10.9+).
     32 class VTVideoDecodeAccelerator
     33     : public media::VideoDecodeAccelerator,
     34       public base::NonThreadSafe {
     35  public:
     36   explicit VTVideoDecodeAccelerator(CGLContextObj cgl_context);
     37   virtual ~VTVideoDecodeAccelerator();
     38 
     39   // VideoDecodeAccelerator implementation.
     40   virtual bool Initialize(
     41       media::VideoCodecProfile profile,
     42       Client* client) OVERRIDE;
     43   virtual void Decode(const media::BitstreamBuffer& bitstream) OVERRIDE;
     44   virtual void AssignPictureBuffers(
     45       const std::vector<media::PictureBuffer>& pictures) OVERRIDE;
     46   virtual void ReusePictureBuffer(int32_t picture_id) OVERRIDE;
     47   virtual void Flush() OVERRIDE;
     48   virtual void Reset() OVERRIDE;
     49   virtual void Destroy() OVERRIDE;
     50   virtual bool CanDecodeOnIOThread() OVERRIDE;
     51 
     52   // Called by OutputThunk() when VideoToolbox finishes decoding a frame.
     53   void Output(
     54       int32_t bitstream_id,
     55       OSStatus status,
     56       CVImageBufferRef image_buffer);
     57 
     58  private:
     59   struct DecodedFrame {
     60     DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer);
     61     ~DecodedFrame();
     62 
     63     int32_t bitstream_id;
     64     base::ScopedCFTypeRef<CVImageBufferRef> image_buffer;
     65   };
     66 
     67   // Actions are the possible types of pending operations, which are queued
     68   // by Flush(), Reset(), and Destroy().
     69   enum Action {
     70     ACTION_FLUSH,
     71     ACTION_RESET,
     72     ACTION_DESTROY
     73   };
     74 
     75   // PendingActions contain the |bitstream_id| of a frame that, once decoded and
     76   // sent, a particular |action| should be completed at.
     77   struct PendingAction {
     78     PendingAction(Action action, int32_t bitstream_id);
     79     ~PendingAction();
     80 
     81     Action action;
     82     int32_t bitstream_id;
     83   };
     84 
     85   // Methods for interacting with VideoToolbox. Run on |decoder_thread_|.
     86   void ConfigureDecoder(
     87       const std::vector<const uint8_t*>& nalu_data_ptrs,
     88       const std::vector<size_t>& nalu_data_sizes);
     89   void DecodeTask(const media::BitstreamBuffer);
     90   void FlushTask();
     91 
     92   // Methods for interacting with |client_|. Run on |gpu_task_runner_|.
     93   void OutputTask(DecodedFrame frame);
     94   void SizeChangedTask(gfx::Size coded_size);
     95 
     96   // Send decoded frames up to and including |up_to_bitstream_id|, and return
     97   // the last sent |bitstream_id|.
     98   int32_t SendPictures(int32_t up_to_bitstream_id);
     99 
    100   // Since VideoToolbox has no reset feature (only flush), and the VDA API
    101   // allows Decode() and Flush() calls during a reset operation, it's possible
    102   // to have multiple pending actions at once. We handle the fully general case
    103   // of an arbitrary sequence of pending actions (in reality, there should
    104   // probably be at most one reset and one flush at a time).
    105   void QueueAction(Action action);
    106 
    107   // Process queued decoded frames, usually by sending them (unless there
    108   // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are
    109   // dropped), completing queued actions along the way.
    110   void ProcessDecodedFrames();
    111 
    112   // Complete a particular action, by eg. calling NotifyFlushDone().
    113   // Warning: Deletes |this| if |action| is ACTION_DESTROY.
    114   void CompleteAction(Action action);
    115 
    116   // Complete all actions pending for a particular |bitstream_id|.
    117   // Warning: Do not call if there is a pending ACTION_DESTROY.
    118   void CompleteActions(int32_t bitstream_id);
    119 
    120   //
    121   // GPU thread state.
    122   //
    123   CGLContextObj cgl_context_;
    124   media::VideoDecodeAccelerator::Client* client_;
    125   gfx::Size texture_size_;
    126   std::queue<PendingAction> pending_actions_;
    127   std::queue<int32_t> pending_bitstream_ids_;
    128 
    129   // Texture IDs of pictures.
    130   // TODO(sandersd): A single map of structs holding picture data.
    131   std::map<int32_t, uint32_t> texture_ids_;
    132 
    133   // Pictures ready to be rendered to.
    134   std::queue<int32_t> available_picture_ids_;
    135 
    136   // Decoded frames ready to render.
    137   std::queue<DecodedFrame> decoded_frames_;
    138 
    139   // Image buffers kept alive while they are bound to pictures.
    140   std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_;
    141 
    142   //
    143   // Decoder thread state.
    144   //
    145   VTDecompressionOutputCallbackRecord callback_;
    146   base::ScopedCFTypeRef<CMFormatDescriptionRef> format_;
    147   base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
    148   media::H264Parser parser_;
    149   gfx::Size coded_size_;
    150 
    151   //
    152   // Shared state (set up and torn down on GPU thread).
    153   //
    154   scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
    155 
    156   // This WeakPtrFactory does not need to be last as its pointers are bound to
    157   // the same thread it is destructed on (the GPU thread).
    158   base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_;
    159 
    160   // Declared last to ensure that all decoder thread tasks complete before any
    161   // state is destructed.
    162   base::Thread decoder_thread_;
    163 
    164   DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator);
    165 };
    166 
    167 }  // namespace content
    168 
    169 #endif  // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
    170