Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 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 // This file contains an implementation of a class that provides H264 decode
      6 // support for use with VAAPI hardware video decode acceleration on Intel
      7 // systems.
      8 
      9 #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
     10 #define CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
     11 
     12 #include <vector>
     13 
     14 #include "base/callback_forward.h"
     15 #include "base/memory/linked_ptr.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "content/common/gpu/media/h264_dpb.h"
     19 #include "content/common/gpu/media/h264_parser.h"
     20 #include "content/common/gpu/media/vaapi_wrapper.h"
     21 #include "media/base/limits.h"
     22 
     23 namespace content {
     24 
     25 // An H264 decoder that utilizes VA-API. Provides features not supported by
     26 // the VA-API userspace library (libva), including stream parsing, reference
     27 // picture management and other operations not supported by the HW codec.
     28 //
     29 // Provides functionality to allow plugging VAAPI HW acceleration into the
     30 // VDA framework.
     31 //
     32 // Clients of this class are expected to pass H264 Annex-B byte stream and
     33 // will receive decoded surfaces via client-provided |OutputPicCB|.
     34 //
     35 // This class must be created, called and destroyed on a single thread, and
     36 // does nothing internally on any other thread.
     37 class VaapiH264Decoder {
     38  public:
     39   // Callback invoked on the client when a surface is to be displayed.
     40   // Arguments: input buffer id provided at the time of Decode()
     41   // and VASurface to output.
     42   typedef base::Callback<
     43       void(int32, const scoped_refptr<VASurface>&)> OutputPicCB;
     44 
     45   enum VAVDAH264DecoderFailure {
     46     FRAME_MBS_ONLY_FLAG_NOT_ONE = 0,
     47     GAPS_IN_FRAME_NUM = 1,
     48     MID_STREAM_RESOLUTION_CHANGE = 2,
     49     INTERLACED_STREAM = 3,
     50     VAAPI_ERROR = 4,
     51     VAVDA_H264_DECODER_FAILURES_MAX,
     52   };
     53 
     54   // Callback to report errors for UMA purposes, not used to return errors
     55   // to clients.
     56   typedef base::Callback<void(VAVDAH264DecoderFailure error)>
     57       ReportErrorToUmaCB;
     58 
     59   // Decode result codes.
     60   enum DecResult {
     61     kDecodeError,  // Error while decoding.
     62     // TODO posciak: unsupported streams are currently treated as error
     63     // in decoding; in future it could perhaps be possible to fall back
     64     // to software decoding instead.
     65     // kStreamError,  // Error in stream.
     66     kAllocateNewSurfaces,  // Need a new set of surfaces to be allocated.
     67     kRanOutOfStreamData,  // Need more stream data to proceed.
     68     kRanOutOfSurfaces,  // Waiting for the client to free up output surfaces.
     69   };
     70 
     71   // |vaapi_wrapper| should be initialized.
     72   // |output_pic_cb| notifies the client a surface is to be displayed.
     73   // |report_error_to_uma_cb| called on errors for UMA purposes, not used
     74   // to report errors to clients.
     75   VaapiH264Decoder(VaapiWrapper* vaapi_wrapper,
     76                    const OutputPicCB& output_pic_cb,
     77                    const ReportErrorToUmaCB& report_error_to_uma_cb);
     78 
     79   ~VaapiH264Decoder();
     80 
     81   // Have the decoder flush its state and trigger output of all previously
     82   // decoded surfaces via OutputPicCB. Return false on failure.
     83   bool Flush() WARN_UNUSED_RESULT;
     84 
     85   // To be called during decoding.
     86   // Stop (pause) decoding, discarding all remaining inputs and outputs,
     87   // but do not flush decoder state, so that the playback can be resumed later,
     88   // possibly from a different location.
     89   void Reset();
     90 
     91   // Set current stream data pointer to |ptr| and |size|. Output surfaces
     92   // that are decoded from data in this stream chunk are to be returned along
     93   // with the given |input_id|.
     94   void SetStream(uint8* ptr, size_t size, int32 input_id);
     95 
     96   // Try to decode more of the stream, returning decoded frames asynchronously
     97   // via output_pic_cb_. Return when more stream is needed, when we run out
     98   // of free surfaces, when we need a new set of them, or when an error occurs.
     99   DecResult Decode() WARN_UNUSED_RESULT;
    100 
    101   // Return dimensions/required number of output surfaces that client should
    102   // be ready to provide for the decoder to function properly.
    103   // To be used after Decode() returns kNeedNewSurfaces.
    104   gfx::Size GetPicSize() { return pic_size_; }
    105   size_t GetRequiredNumOfPictures();
    106 
    107   // To be used by the client to feed decoder with output surfaces.
    108   void ReuseSurface(const scoped_refptr<VASurface>& va_surface);
    109 
    110  private:
    111   // We need to keep at most kDPBMaxSize pictures in DPB for
    112   // reference/to display later and an additional one for the one currently
    113   // being decoded. We also ask for some additional ones since VDA needs
    114   // to accumulate a few ready-to-output pictures before it actually starts
    115   // displaying and giving them back. +2 instead of +1 because of subjective
    116   // smoothness improvement during testing.
    117   enum {
    118     kPicsInPipeline = media::limits::kMaxVideoFrames + 2,
    119     kMaxNumReqPictures = H264DPB::kDPBMaxSize + kPicsInPipeline,
    120   };
    121 
    122   // Internal state of the decoder.
    123   enum State {
    124     kNeedStreamMetadata,  // After initialization, need an SPS.
    125     kDecoding,  // Ready to decode from any point.
    126     kAfterReset, // After Reset(), need a resume point.
    127     kError,  // Error in decode, can't continue.
    128   };
    129 
    130   // Process H264 stream structures.
    131   bool ProcessSPS(int sps_id, bool* need_new_buffers);
    132   bool ProcessPPS(int pps_id);
    133   bool ProcessSlice(H264SliceHeader* slice_hdr);
    134 
    135   // Initialize the current picture according to data in |slice_hdr|.
    136   bool InitCurrPicture(H264SliceHeader* slice_hdr);
    137 
    138   // Calculate picture order counts for the new picture
    139   // on initialization of a new frame (see spec).
    140   bool CalculatePicOrderCounts(H264SliceHeader* slice_hdr);
    141 
    142   // Update PicNum values in pictures stored in DPB on creation of new
    143   // frame (see spec).
    144   void UpdatePicNums();
    145 
    146   // Prepare reference picture lists (ref_pic_list[01]_).
    147   bool PrepareRefPicLists(H264SliceHeader* slice_hdr);
    148 
    149   // Construct initial reference picture lists for use in decoding of
    150   // P and B pictures (see 8.2.4 in spec).
    151   void ConstructReferencePicListsP(H264SliceHeader* slice_hdr);
    152   void ConstructReferencePicListsB(H264SliceHeader* slice_hdr);
    153 
    154   // Helper functions for reference list construction, per spec.
    155   int PicNumF(H264Picture *pic);
    156   int LongTermPicNumF(H264Picture *pic);
    157 
    158   // Perform the reference picture lists' modification (reordering), as
    159   // specified in spec (8.2.4).
    160   //
    161   // |list| indicates list number and should be either 0 or 1.
    162   bool ModifyReferencePicList(H264SliceHeader *slice_hdr, int list);
    163 
    164   // Perform reference picture memory management operations (marking/unmarking
    165   // of reference pictures, long term picture management, discarding, etc.).
    166   // See 8.2.5 in spec.
    167   bool HandleMemoryManagementOps();
    168   void ReferencePictureMarking();
    169 
    170   // Start processing a new frame.
    171   bool StartNewFrame(H264SliceHeader* slice_hdr);
    172 
    173   // All data for a frame received, process it and decode.
    174   bool FinishPrevFrameIfPresent();
    175 
    176   // Called after decoding, performs all operations to be done after decoding,
    177   // including DPB management, reference picture marking and memory management
    178   // operations.
    179   // This will also output a picture if one is ready for output.
    180   bool FinishPicture();
    181 
    182   // Clear DPB contents and remove all surfaces in DPB from *in_use_ list.
    183   // Cleared pictures will be made available for decode, unless they are
    184   // at client waiting to be displayed.
    185   void ClearDPB();
    186 
    187   // These queue up data for HW decoder to be committed on running HW decode.
    188   bool SendPPS();
    189   bool SendIQMatrix();
    190   bool SendVASliceParam(H264SliceHeader* slice_hdr);
    191   bool SendSliceData(const uint8* ptr, size_t size);
    192   bool QueueSlice(H264SliceHeader* slice_hdr);
    193 
    194   // Helper methods for filling HW structures.
    195   void FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic);
    196   int FillVARefFramesFromDPB(VAPictureH264 *va_pics, int num_pics);
    197 
    198   // Commits all pending data for HW decoder and starts HW decoder.
    199   bool DecodePicture();
    200 
    201   // Notifies client that a picture is ready for output.
    202   bool OutputPic(H264Picture* pic);
    203 
    204   // Output all pictures in DPB that have not been outputted yet.
    205   bool OutputAllRemainingPics();
    206 
    207   // Represents a frame being decoded. Will always have a VASurface
    208   // assigned to it, which will eventually contain decoded picture data.
    209   class DecodeSurface;
    210 
    211   // Assign an available surface to the given PicOrderCnt |poc|,
    212   // removing it from the available surfaces pool. Return true if a surface
    213   // has been found, false otherwise.
    214   bool AssignSurfaceToPoC(int32 input_id, int poc);
    215 
    216   // Indicate that a surface is no longer needed by decoder.
    217   void UnassignSurfaceFromPoC(int poc);
    218 
    219   // Return DecodeSurface assigned to |poc|.
    220   DecodeSurface* DecodeSurfaceByPoC(int poc);
    221 
    222   // Decoder state.
    223   State state_;
    224 
    225   // Parser in use.
    226   H264Parser parser_;
    227 
    228   // DPB in use.
    229   H264DPB dpb_;
    230 
    231   // Picture currently being processed/decoded.
    232   scoped_ptr<H264Picture> curr_pic_;
    233 
    234   // Reference picture lists, constructed for each picture before decoding.
    235   // Those lists are not owners of the pointers (DPB is).
    236   H264Picture::PtrVector ref_pic_list0_;
    237   H264Picture::PtrVector ref_pic_list1_;
    238 
    239   // Global state values, needed in decoding. See spec.
    240   int max_pic_order_cnt_lsb_;
    241   int max_frame_num_;
    242   int max_pic_num_;
    243   int max_long_term_frame_idx_;
    244 
    245   int frame_num_;
    246   int prev_frame_num_;
    247   int prev_frame_num_offset_;
    248   bool prev_has_memmgmnt5_;
    249 
    250   // Values related to previously decoded reference picture.
    251   bool prev_ref_has_memmgmnt5_;
    252   int prev_ref_top_field_order_cnt_;
    253   int prev_ref_pic_order_cnt_msb_;
    254   int prev_ref_pic_order_cnt_lsb_;
    255   H264Picture::Field prev_ref_field_;
    256 
    257   // Currently active SPS and PPS.
    258   int curr_sps_id_;
    259   int curr_pps_id_;
    260 
    261   // Output picture size.
    262   gfx::Size pic_size_;
    263 
    264   // Maps H.264 PicOrderCount to currently used DecodeSurfaces;
    265   typedef std::map<int, linked_ptr<DecodeSurface> > DecSurfacesInUse;
    266   DecSurfacesInUse decode_surfaces_in_use_;
    267 
    268   // Unused VA surfaces returned by client, ready to be reused.
    269   std::vector<scoped_refptr<VASurface> > available_va_surfaces_;
    270 
    271   // The id of current input buffer, which will be associated with an
    272   // output surface when a frame is successfully decoded.
    273   int32 curr_input_id_;
    274 
    275   VaapiWrapper* vaapi_wrapper_;
    276 
    277   // Called by decoder when a surface should be outputted.
    278   OutputPicCB output_pic_cb_;
    279 
    280   // Called to report decoding error to UMA, not used to indicate errors
    281   // to clients.
    282   ReportErrorToUmaCB report_error_to_uma_cb_;
    283 
    284   // PicOrderCount of the previously outputted frame.
    285   int last_output_poc_;
    286 
    287   // Maximum size of DPB required by codec level.
    288   int max_dpb_size_;
    289 
    290   DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder);
    291 };
    292 
    293 }  // namespace content
    294 
    295 #endif  // CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
    296