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