| OLD | NEW |
| (Empty) |
| 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/vaapi_h264_dpb.h" | |
| 19 #include "content/common/gpu/media/vaapi_wrapper.h" | |
| 20 #include "media/base/limits.h" | |
| 21 #include "media/filters/h264_parser.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 CONTENT_EXPORT 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(const 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 = VaapiH264DPB::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(media::H264SliceHeader* slice_hdr); | |
| 134 | |
| 135 // Initialize the current picture according to data in |slice_hdr|. | |
| 136 bool InitCurrPicture(media::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(media::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 bool UpdateMaxNumReorderFrames(const media::H264SPS* sps); | |
| 147 | |
| 148 // Prepare reference picture lists (ref_pic_list[01]_). | |
| 149 bool PrepareRefPicLists(media::H264SliceHeader* slice_hdr); | |
| 150 | |
| 151 // Construct initial reference picture lists for use in decoding of | |
| 152 // P and B pictures (see 8.2.4 in spec). | |
| 153 void ConstructReferencePicListsP(media::H264SliceHeader* slice_hdr); | |
| 154 void ConstructReferencePicListsB(media::H264SliceHeader* slice_hdr); | |
| 155 | |
| 156 // Helper functions for reference list construction, per spec. | |
| 157 int PicNumF(VaapiH264Picture *pic); | |
| 158 int LongTermPicNumF(VaapiH264Picture *pic); | |
| 159 | |
| 160 // Perform the reference picture lists' modification (reordering), as | |
| 161 // specified in spec (8.2.4). | |
| 162 // | |
| 163 // |list| indicates list number and should be either 0 or 1. | |
| 164 bool ModifyReferencePicList(media::H264SliceHeader* slice_hdr, int list); | |
| 165 | |
| 166 // Perform reference picture memory management operations (marking/unmarking | |
| 167 // of reference pictures, long term picture management, discarding, etc.). | |
| 168 // See 8.2.5 in spec. | |
| 169 bool HandleMemoryManagementOps(); | |
| 170 void ReferencePictureMarking(); | |
| 171 | |
| 172 // Start processing a new frame. | |
| 173 bool StartNewFrame(media::H264SliceHeader* slice_hdr); | |
| 174 | |
| 175 // All data for a frame received, process it and decode. | |
| 176 bool FinishPrevFrameIfPresent(); | |
| 177 | |
| 178 // Called after decoding, performs all operations to be done after decoding, | |
| 179 // including DPB management, reference picture marking and memory management | |
| 180 // operations. | |
| 181 // This will also output a picture if one is ready for output. | |
| 182 bool FinishPicture(); | |
| 183 | |
| 184 // Clear DPB contents and remove all surfaces in DPB from *in_use_ list. | |
| 185 // Cleared pictures will be made available for decode, unless they are | |
| 186 // at client waiting to be displayed. | |
| 187 void ClearDPB(); | |
| 188 | |
| 189 // These queue up data for HW decoder to be committed on running HW decode. | |
| 190 bool SendPPS(); | |
| 191 bool SendIQMatrix(); | |
| 192 bool SendVASliceParam(media::H264SliceHeader* slice_hdr); | |
| 193 bool SendSliceData(const uint8* ptr, size_t size); | |
| 194 bool QueueSlice(media::H264SliceHeader* slice_hdr); | |
| 195 | |
| 196 // Helper methods for filling HW structures. | |
| 197 void FillVAPicture(VAPictureH264 *va_pic, VaapiH264Picture* pic); | |
| 198 int FillVARefFramesFromDPB(VAPictureH264 *va_pics, int num_pics); | |
| 199 | |
| 200 // Commits all pending data for HW decoder and starts HW decoder. | |
| 201 bool DecodePicture(); | |
| 202 | |
| 203 // Notifies client that a picture is ready for output. | |
| 204 bool OutputPic(VaapiH264Picture* pic); | |
| 205 | |
| 206 // Output all pictures in DPB that have not been outputted yet. | |
| 207 bool OutputAllRemainingPics(); | |
| 208 | |
| 209 // Represents a frame being decoded. Will always have a VASurface | |
| 210 // assigned to it, which will eventually contain decoded picture data. | |
| 211 class DecodeSurface; | |
| 212 | |
| 213 // Assign an available surface to the given PicOrderCnt |poc|, | |
| 214 // removing it from the available surfaces pool. Return true if a surface | |
| 215 // has been found, false otherwise. | |
| 216 bool AssignSurfaceToPoC(int32 input_id, int poc); | |
| 217 | |
| 218 // Indicate that a surface is no longer needed by decoder. | |
| 219 void UnassignSurfaceFromPoC(int poc); | |
| 220 | |
| 221 // Return DecodeSurface assigned to |poc|. | |
| 222 DecodeSurface* DecodeSurfaceByPoC(int poc); | |
| 223 | |
| 224 // Decoder state. | |
| 225 State state_; | |
| 226 | |
| 227 // Parser in use. | |
| 228 media::H264Parser parser_; | |
| 229 | |
| 230 // DPB in use. | |
| 231 VaapiH264DPB dpb_; | |
| 232 | |
| 233 // Picture currently being processed/decoded. | |
| 234 scoped_ptr<VaapiH264Picture> curr_pic_; | |
| 235 | |
| 236 // Reference picture lists, constructed for each picture before decoding. | |
| 237 // Those lists are not owners of the pointers (DPB is). | |
| 238 VaapiH264Picture::PtrVector ref_pic_list0_; | |
| 239 VaapiH264Picture::PtrVector ref_pic_list1_; | |
| 240 | |
| 241 // Global state values, needed in decoding. See spec. | |
| 242 int max_pic_order_cnt_lsb_; | |
| 243 int max_frame_num_; | |
| 244 int max_pic_num_; | |
| 245 int max_long_term_frame_idx_; | |
| 246 size_t max_num_reorder_frames_; | |
| 247 | |
| 248 int frame_num_; | |
| 249 int prev_frame_num_; | |
| 250 int prev_frame_num_offset_; | |
| 251 bool prev_has_memmgmnt5_; | |
| 252 | |
| 253 // Values related to previously decoded reference picture. | |
| 254 bool prev_ref_has_memmgmnt5_; | |
| 255 int prev_ref_top_field_order_cnt_; | |
| 256 int prev_ref_pic_order_cnt_msb_; | |
| 257 int prev_ref_pic_order_cnt_lsb_; | |
| 258 VaapiH264Picture::Field prev_ref_field_; | |
| 259 | |
| 260 // Currently active SPS and PPS. | |
| 261 int curr_sps_id_; | |
| 262 int curr_pps_id_; | |
| 263 | |
| 264 // Output picture size. | |
| 265 gfx::Size pic_size_; | |
| 266 | |
| 267 // Maps H.264 PicOrderCount to currently used DecodeSurfaces; | |
| 268 typedef std::map<int, linked_ptr<DecodeSurface> > DecSurfacesInUse; | |
| 269 DecSurfacesInUse decode_surfaces_in_use_; | |
| 270 | |
| 271 // Unused VA surfaces returned by client, ready to be reused. | |
| 272 std::vector<scoped_refptr<VASurface> > available_va_surfaces_; | |
| 273 | |
| 274 // The id of current input buffer, which will be associated with an | |
| 275 // output surface when a frame is successfully decoded. | |
| 276 int32 curr_input_id_; | |
| 277 | |
| 278 VaapiWrapper* vaapi_wrapper_; | |
| 279 | |
| 280 // Called by decoder when a surface should be outputted. | |
| 281 OutputPicCB output_pic_cb_; | |
| 282 | |
| 283 // Called to report decoding error to UMA, not used to indicate errors | |
| 284 // to clients. | |
| 285 ReportErrorToUmaCB report_error_to_uma_cb_; | |
| 286 | |
| 287 // PicOrderCount of the previously outputted frame. | |
| 288 int last_output_poc_; | |
| 289 | |
| 290 DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder); | |
| 291 }; | |
| 292 | |
| 293 } // namespace content | |
| 294 | |
| 295 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_ | |
| OLD | NEW |