blob: 9774b1d9ef5bb70e9877e2a8317e2968958bd07f [file] [log] [blame]
// Copyright 2022 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_H264_DECODER_H_
#define MEDIA_GPU_V4L2_TEST_H264_DECODER_H_
// build_config.h must come before BUILDFLAG()
#include "build/build_config.h"
// ChromeOS specific header; does not exist upstream
#if BUILDFLAG(IS_CHROMEOS)
#include <linux/media/h264-ctrls-upstream.h>
#endif
#include "base/files/memory_mapped_file.h"
#include "media/gpu/v4l2/test/h264_dpb.h"
#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h"
#include "media/gpu/v4l2/test/video_decoder.h"
namespace media {
namespace v4l2_test {
// PreviousRefPicOrder contains data regarding the picture
// order counts for the previously decoded frame.
struct PreviousRefPicOrder {
int prev_ref_pic_order_cnt_msb = 0;
int prev_ref_pic_order_cnt_lsb = 0;
};
class H264Decoder : public VideoDecoder {
public:
H264Decoder(const H264Decoder&) = delete;
H264Decoder& operator=(const H264Decoder&) = delete;
~H264Decoder() override;
// Creates a H264Decoder after verifying that the bitstream is h.264
// and the underlying implementation supports H.264 slice decoding.
static std::unique_ptr<H264Decoder> Create(
const base::MemoryMappedFile& stream);
// Parses next frame from IVF stream 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(std::vector<uint8_t>& y_plane,
std::vector<uint8_t>& u_plane,
std::vector<uint8_t>& v_plane,
gfx::Size& size,
const int frame_number) override;
private:
H264Decoder(std::unique_ptr<H264Parser> parser,
std::unique_ptr<V4L2IoctlShim> v4l2_ioctl,
gfx::Size display_resolution,
int sps_id);
// Processes NALU's until reaching the end of the current frame. To
// know the end of the current frame it may be necessary to start parsing
// the next frame. If this occurs the NALU that was parsed needs to be
// held over until the next frame. This is done in |pending_nalu_|
// Not every frame has a SPS/PPS associated with it. The SPS/PPS must
// occur on an IDR frame. Store the last seen slice header in
// |pending_slice_header_| so it will be available for the next frame.
H264Parser::Result ProcessNextFrame(
const int frame_number,
std::unique_ptr<H264SliceHeader>* resulting_slice_header);
// Sends IOCTL call to device with the frame's SPS, PPS, and Scaling Matrix
// data which indicates the beginning of a new frame.
VideoDecoder::Result StartNewFrame(
int sps_id,
int pps_id,
H264SliceHeader* slice_hdr,
H264SliceMetadata* slice_metadata,
v4l2_ctrl_h264_decode_params* v4l2_decode_param);
// Finishes frame processing for the current decoded frame. Transmits decode
// parameters via IOCTL Ext Ctrls. It continues to execute decoded ref
// picture marking process as defined in section 8.2.5. Finally, using
// the DPB, transmit H264 Slices to the device for the current frame.
VideoDecoder::Result FinishFrame(
const H264SliceHeader& curr_slice,
int frame_num,
v4l2_ctrl_h264_decode_params& v4l2_decode_param,
H264SliceMetadata& slice_metadata,
bool is_OUTPUT_queue_new);
// Initializes H264 Slice Metadata based on slice header and
// based on H264 specifications which it calculates its pic order count.
VideoDecoder::Result InitializeSliceMetadata(
const H264SliceHeader& slice_hdr,
const H264SPS* sps,
H264SliceMetadata* slice_metadata) const;
// Returns all CAPTURE buffer indexes that can be reused for a
// VIDIOC_QBUF ioctl call.
std::set<uint32_t> GetReusableReferenceSlots(
const MmappedBuffer& buffer,
std::set<uint32_t> queued_buffer_ids);
// Calculates decoding parameters based on SPS corresponding to sps_id.
// If decoding parameters change, this can result in flushing the DPB.
void ProcessSPS(const int sps_id);
// Moves all non output pictures in the DPB to the slice_ready_queue.
// Finishes by clearing the entire DPB.
void FlushDPB();
const std::unique_ptr<H264Parser> parser_;
// Previous pic order counts from previous frame
PreviousRefPicOrder prev_pic_order_;
int global_pic_count_ = 0;
H264DPB dpb_;
// Number of non-outputted pictures needed in DPB before a picture
// can be outputted.
size_t max_num_reorder_frames_;
// Decoding profile parameters
gfx::Size pic_size_;
VideoCodecProfile profile_;
uint8_t bit_depth_ = -1;
int prev_frame_num_ = -1;
int prev_frame_num_offset_ = -1;
std::unique_ptr<H264NALU> pending_nalu_;
std::unique_ptr<H264SliceHeader> pending_slice_header_;
};
} // namespace v4l2_test
} // namespace media
#endif // MEDIA_GPU_V4L2_TEST_H264_DECODER_H_