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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_V4L2_TEST_H265_DECODER_H_
#define MEDIA_GPU_V4L2_TEST_H265_DECODER_H_
#include <queue>
#include "base/memory/raw_ref.h"
#include "media/base/video_codecs.h"
#include "media/gpu/v4l2/test/h265_dpb.h"
#include "media/gpu/v4l2/test/video_decoder.h"
#include "media/parsers/h265_parser.h"
namespace media {
namespace v4l2_test {
class H265Decoder : public VideoDecoder {
public:
H265Decoder(const H265Decoder&) = delete;
H265Decoder& operator=(const H265Decoder&) = delete;
~H265Decoder() override;
// Creates a H265Decoder after verifying that the bitstream is HEVC
// and the underlying implementation supports HEVC slice decoding.
static std::unique_ptr<H265Decoder> Create(
const base::MemoryMappedFile& stream);
// Parses next frame from the input and decodes the frame. This method will
// place the Y, U, and V values into the respective vectors and update the
// size with the display area size of the decoded frame.
VideoDecoder::Result DecodeNextFrame(const int frame_number,
std::vector<uint8_t>& y_plane,
std::vector<uint8_t>& u_plane,
std::vector<uint8_t>& v_plane,
gfx::Size& size,
BitDepth& bit_depth) override;
private:
H265Decoder(std::unique_ptr<V4L2IoctlShim> v4l2_ioctl,
gfx::Size display_resolution,
const base::MemoryMappedFile& data_stream);
// Internal state of the decoder.
enum State {
// Ready to decode from any point.
kDecoding,
// After Reset(), need a resume point.
kAfterReset,
// The following keep track of what step is next in Decode() processing
// in order to resume properly after H265Decoder::kTryAgain (or another
// retryable error) is returned. The next time Decode() is called the call
// that previously failed will be retried and execution continues from
// there (if possible).
// Processes PPS before processing the current slice.
kTryPreprocessCurrentSlice,
// Makes sure processing the previous frame is finished.
kEnsurePicture,
// Processes a new frame.
kTryNewFrame,
// Processes the current slice.
kTryCurrentSlice,
// Error in decode, can't continue.
kError,
};
enum DecodeResult {
kConfigChange, // This is returned when some configuration (e.g.
// profile or picture size) is changed. A client may
// need to apply the client side configuration
// properly (e.g. allocate buffers with the new
// resolution).
kRanOutOfStreamData, // Need more stream data to proceed.
kOk,
};
// Output all pictures in DPB that have not been outputted yet.
bool OutputAllRemainingPics();
// Output all pictures in DPB and clear the DPB.
bool Flush();
// Process H265 bitstream PPS (picture parameter set).
bool ProcessPPS(int pps_id, bool* need_new_buffers);
// Process current slice header to discover if we need to start a new picture,
// finishing up the current one.
bool PreprocessCurrentSlice();
// Process current slice as a slice of the current picture.
bool ProcessCurrentSlice();
// Calculates the picture output flags using |slice_hdr| for |curr_pic_|.
void CalcPicOutputFlags(const H265SliceHeader* slice_hdr);
// Calculates picture order count (POC) using |pps| and|slice_hdr| for
// |curr_pic_|.
void CalcPictureOrderCount(const H265PPS* pps,
const H265SliceHeader* slice_hdr);
// Calculates the POCs for the reference pictures for |curr_pic_| using
// |sps|, |pps| and |slice_hdr| and stores them in the member variables.
// Returns false if bitstream conformance is not maintained, true otherwise.
bool CalcRefPicPocs(const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr);
// Builds the reference pictures lists for |curr_pic_| using |sps|, |pps|,
// |slice_hdr| and the member variables calculated in CalcRefPicPocs. Returns
// false if bitstream conformance is not maintained or needed reference
// pictures are missing, true otherwise. At the end of this,
// |ref_pic_list{0,1}| will be populated with the required reference pictures
// for submitting to the accelerator.
bool BuildRefPicLists(const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr);
// Notifies client that a picture is ready for output.
bool OutputPic(scoped_refptr<H265Picture> pic);
// Performs DPB management operations for |curr_pic_| by removing no longer
// needed entries from the DPB and outputting pictures from the DPB. |sps|
// should be the corresponding SPS for |curr_pic_|.
bool PerformDpbOperations(const H265SPS* sps);
// Start processing a new frame. This also generates all the POC and output
// variables for the frame, generates reference picture lists, performs
// reference picture marking, DPB management and picture output.
bool StartNewFrame(const H265SliceHeader* slice_hdr);
// Returns all CAPTURE buffer indexes that can be reused
// for VIDIOC_QBUF ioctl call.
std::set<uint32_t> GetReusableReferenceSlots(
const MmappedBuffer& buffer,
const std::set<uint32_t>& queued_buffer_ids);
// Commits all pending data for HW decoder and starts HW decoder.
bool DecodePicture();
// Called after we are done processing |pic|.
void FinishPicture(scoped_refptr<H265Picture> pic);
// All data for a frame received, process it and decode.
void FinishPrevFrameIfPresent();
// This is the main method used for running the decode loop. It will try to
// decode all frames in the stream until there is a configuration change,
// error or the end of the stream is reached.
DecodeResult Decode();
// Decoder state.
State state_ = kAfterReset;
std::unique_ptr<H265Parser> parser_;
// DPB in use.
H265DPB dpb_;
// Picture currently being processed/decoded.
scoped_refptr<H265Picture> curr_pic_;
int global_pic_count_ = 0;
// Used to identify first picture in decoding order
// or first picture that follows an EOS NALU.
bool first_picture_ = true;
const raw_ref<const base::MemoryMappedFile> data_stream_;
// Global state values needed for decoding. See spec.
scoped_refptr<H265Picture> prev_tid0_pic_;
int max_pic_order_cnt_lsb_;
bool curr_delta_poc_msb_present_flag_[kMaxDpbSize];
bool foll_delta_poc_msb_present_flag_[kMaxDpbSize];
int num_poc_st_curr_before_;
int num_poc_st_curr_after_;
int num_poc_st_foll_;
int num_poc_lt_curr_;
int num_poc_lt_foll_;
int poc_st_curr_before_[kMaxDpbSize];
int poc_st_curr_after_[kMaxDpbSize];
int poc_st_foll_[kMaxDpbSize];
int poc_lt_curr_[kMaxDpbSize];
int poc_lt_foll_[kMaxDpbSize];
H265Picture::Vector ref_pic_list0_;
H265Picture::Vector ref_pic_list1_;
H265Picture::Vector ref_pic_set_lt_curr_;
H265Picture::Vector ref_pic_set_st_curr_after_;
H265Picture::Vector ref_pic_set_st_curr_before_;
// |ref_pic_list_| is the collection of all pictures from StCurrBefore,
// StCurrAfter, StFoll, LtCurr and LtFoll.
H265Picture::Vector ref_pic_list_;
// Currently active SPS and PPS.
int curr_sps_id_ = -1;
int curr_pps_id_ = -1;
// Current NALU and slice header being processed.
std::unique_ptr<H265NALU> curr_nalu_;
std::unique_ptr<H265SliceHeader> curr_slice_hdr_;
std::unique_ptr<H265SliceHeader> last_slice_hdr_;
// Output picture size.
gfx::Size pic_size_;
// Output visible cropping rect.
gfx::Rect visible_rect_;
// Profile of input bitstream.
VideoCodecProfile profile_;
// Bit depth of input bitstream.
uint8_t bit_depth_ = 0;
// Chroma sampling format of input bitstream.
VideoChromaSampling chroma_sampling_ = VideoChromaSampling::kUnknown;
// If this is true, then the entire steam has been parsed.
bool is_stream_over_ = false;
// Checks whether |OUTPUT_queue_| is newly created at the current frame.
bool is_OUTPUT_queue_new_ = true;
// Stores decoded frames ready to be outputted in a queue.
std::queue<scoped_refptr<H265Picture>> frames_ready_to_be_outputted_;
};
} // namespace v4l2_test
} // namespace media
#endif // MEDIA_GPU_V4L2_TEST_H265_DECODER_H_
|