blob: a335c6f36509adcba20853c71fa3ae11154947a9 [file] [log] [blame]
// Copyright 2021 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_VAAPI_TEST_H264_DECODER_H_
#define MEDIA_GPU_VAAPI_TEST_H264_DECODER_H_
#include <queue>
#include "media/gpu/vaapi/test/h264_dpb.h"
#include "media/gpu/vaapi/test/h264_vaapi_wrapper.h"
#include "media/gpu/vaapi/test/video_decoder.h"
#include "media/parsers/h264_parser.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace media {
namespace vaapi_test {
class H264Decoder : public VideoDecoder {
public:
H264Decoder(const uint8_t* stream_data,
size_t stream_len,
const VaapiDevice& va_device,
SharedVASurface::FetchPolicy fetch_policy);
H264Decoder(const H264Decoder&) = delete;
H264Decoder& operator=(const H264Decoder&) = delete;
~H264Decoder() override;
// VideoDecoder implementation.
VideoDecoder::Result DecodeNextFrame() override;
private:
// Decode the next frame in the bitstream.
void DecodeNextFrameInStream();
// Process a slice.
void ProcessSlice();
// Process an SPS NALU.
void UpdateSequenceParams();
// Process a PPS NALU.
void UpdatePictureParams();
// Issue the final commands to VAAPI to decode the slices we have been
// inputing.
void DecodeFrame();
// Finalize the picture and handle reference picture buffer memory management.
void FinishPicture(scoped_refptr<H264Picture> pic);
// Process SPS and PPS NALUs until we hit a slice header.
bool GetStreamMetadata();
// Detects if the last slice header refers to a new frame.
bool IsNewFrame();
// Populate some local variables based on a slice NALU.
void ExtractSliceHeader();
// Create a new picture and hand some metadata to VAAPI.
void StartNewFrame();
// Initialize a picture.
bool InitCurrPicture(const H264SliceHeader* slice_hdr);
// Some helper functions for preparing the reference picture buffers. H.264
// has separate P and B frame reference picture buffers.
void ConstructReferencePicListsP();
void ConstructReferencePicListsB();
// Re-order the reference frame buf based on the current frame number.
void UpdatePicNums(int frame_num);
// Some helper functions for handling gaps in the frame data.
bool InitNonexistingPicture(scoped_refptr<H264Picture> pic,
int frame_num,
bool ref);
bool HandleFrameNumGap(int frame_num);
// Calculate Pic Order Counts. This is approximately what we would intuitively
// think of as the frame number in display order, except it wraps around.
bool CalculatePicOrderCounts(scoped_refptr<H264Picture> pic);
void UpdateMaxNumReorderFrames(const H264SPS* sps);
// Populate the reference lists that we send to VAAPI using data from the
// DPB.
bool ModifyReferencePicLists(const H264SliceHeader* slice_hdr,
H264Picture::Vector* ref_pic_list0,
H264Picture::Vector* ref_pic_list1);
bool ModifyReferencePicList(const H264SliceHeader* slice_hdr,
int list,
H264Picture::Vector* ref_pic_listx);
// Helps manage the DPB and mark what we need to keep for reference and what
// we can mark as unused. Note that a frame might still be kept around even if
// it isn't being used as a reference because we might need to output it.
// Normal H.264 decoder implementations have finer grained cache control, but
// since we can only output one picture DecodeNextFrame() call, we have to
// keep a pretty big cache around until the output catches up to the decode.
bool ReferencePictureMarking(scoped_refptr<H264Picture> pic);
bool HandleMemoryManagementOps(scoped_refptr<H264Picture> pic);
bool SlidingWindowPictureMarking();
int PicNumF(const H264Picture& pic) const;
int LongTermPicNumF(const H264Picture& pic) const;
static void ShiftRightAndInsert(H264Picture::Vector* v,
int from,
int to,
scoped_refptr<H264Picture> pic);
// Used for computing how large the DPB should be for each level.
static uint32_t H264LevelToMaxDpbMbs(uint8_t level);
// Output all remaining images in the DPB.
void FlushDPB();
// H.264 NALU parser
std::unique_ptr<H264Parser> parser_;
// The last sequence param id.
int curr_sps_id_;
// The last picture param id.
int curr_pps_id_;
// The last slice header parsed.
std::unique_ptr<H264SliceHeader> curr_slice_hdr_;
// The last NALU that was parsed.
std::unique_ptr<H264NALU> curr_nalu_;
// Picture we are currently decoding. Not necessarily the one we will output
// since H.264 sends pictures out of order.
scoped_refptr<H264Picture> curr_picture_;
// Set once we hit EOS.
bool is_stream_over_;
// Reference picture lists. P = forward prediction, B = bidirectional
// prediction.
H264Picture::Vector ref_pic_list_p0_;
H264Picture::Vector ref_pic_list_b0_;
H264Picture::Vector ref_pic_list_b1_;
// Some primitive related to frame number to help with the ordering of the
// reference pictures. Note that "frame_num" in this instance does not
// intuitively refer to the index of the frame when it gets output, but just
// the index of the frame in the bitstream. Pic order count is more closely
// related to output order, but it can also wrap.
int max_frame_num_;
int max_pic_num_;
int max_long_term_frame_idx_;
size_t max_num_reorder_frames_;
int prev_frame_num_;
int prev_ref_frame_num_;
int prev_frame_num_offset_;
bool prev_has_memmgmnt5_;
// These are std::nullopt unless get recovery point SEI message after Reset.
// A frame_num of the frame at output order that is correct in content.
std::optional<int> recovery_frame_num_;
// A value in the recovery point SEI message to compute |recovery_frame_num_|
// later.
std::optional<int> recovery_frame_cnt_;
// Buffer object to keep track of our reference images.
H264DPB dpb_;
// Some handy abstractions for issuing VAAPI calls.
H264VaapiWrapper va_wrapper_;
// Values related to previously decoded reference picture.
bool prev_ref_has_memmgmnt5_;
int prev_ref_top_field_order_cnt_;
int prev_ref_pic_order_cnt_msb_;
int prev_ref_pic_order_cnt_lsb_;
H264Picture::Field prev_ref_field_;
// The actual size of the output picture.
gfx::Rect visible_rect_;
// Pictures to flush in descending POC order.
std::queue<scoped_refptr<H264Picture>> output_queue;
};
} // namespace vaapi_test
} // namespace media
#endif // MEDIA_GPU_VAAPI_TEST_H264_DECODER_H_