diff options
author | Pin-chih Lin <johnylin@google.com> | 2017-05-18 21:20:21 +0800 |
---|---|---|
committer | Pin-chih Lin <johnylin@google.com> | 2017-05-22 16:07:46 +0800 |
commit | 1f105de0c9b603245dcea0e8213f45ecff7a5707 (patch) | |
tree | 82e15ca304919b592378a0ad5f4d4d0419ced02b | |
parent | f2604506384a4402de1fd5b8e32844663585d0bd (diff) | |
download | v4l2_codec2-1f105de0c9b603245dcea0e8213f45ecff7a5707.tar.gz |
Port h264_dpb from Chromium
Slight modifications
file: src/media/gpu/h264_dpb.*
commit head: 11c7629beff558f7f5822067dcfeb6d6a729d13b
Bug: 32691050
Test: mmm external/v4l2_codec2
Change-Id: I475a32a29b54fa2fb3ebc0dac27fca5d2382721b
-rw-r--r-- | vda/Android.mk | 1 | ||||
-rw-r--r-- | vda/h264_dpb.cc | 166 | ||||
-rw-r--r-- | vda/h264_dpb.h | 171 |
3 files changed, 338 insertions, 0 deletions
diff --git a/vda/Android.mk b/vda/Android.mk index 48e7f3d..b4c3dfb 100644 --- a/vda/Android.mk +++ b/vda/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_CPP_EXTENSION:= .cc LOCAL_SRC_FILES:= \ h264_bit_reader.cc \ + h264_dpb.cc \ h264_parser.cc \ ranges.cc \ diff --git a/vda/h264_dpb.cc b/vda/h264_dpb.cc new file mode 100644 index 0000000..fb4a98d --- /dev/null +++ b/vda/h264_dpb.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string.h> + +#include <algorithm> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "h264_dpb.h" + +namespace media { + +H264Picture::H264Picture() + : pic_order_cnt_type(0), + top_field_order_cnt(0), + bottom_field_order_cnt(0), + pic_order_cnt(0), + pic_order_cnt_msb(0), + pic_order_cnt_lsb(0), + delta_pic_order_cnt_bottom(0), + delta_pic_order_cnt0(0), + delta_pic_order_cnt1(0), + pic_num(0), + long_term_pic_num(0), + frame_num(0), + frame_num_offset(0), + frame_num_wrap(0), + long_term_frame_idx(0), + type(H264SliceHeader::kPSlice), + nal_ref_idc(0), + idr(false), + idr_pic_id(0), + ref(false), + long_term(false), + outputted(false), + mem_mgmt_5(false), + nonexisting(false), + field(FIELD_NONE), + long_term_reference_flag(false), + adaptive_ref_pic_marking_mode_flag(false), + dpb_position(0) { + memset(&ref_pic_marking, 0, sizeof(ref_pic_marking)); +} + +H264Picture::~H264Picture() {} + +H264DPB::H264DPB() : max_num_pics_(0) {} +H264DPB::~H264DPB() {} + +void H264DPB::Clear() { + pics_.clear(); +} + +void H264DPB::set_max_num_pics(size_t max_num_pics) { + DCHECK_LE(max_num_pics, static_cast<size_t>(kDPBMaxSize)); + max_num_pics_ = max_num_pics; + if (pics_.size() > max_num_pics_) + pics_.resize(max_num_pics_); +} + +void H264DPB::UpdatePicPositions() { + size_t i = 0; + for (auto& pic : pics_) { + pic->dpb_position = i; + ++i; + } +} + +void H264DPB::DeleteByPOC(int poc) { + for (H264Picture::Vector::iterator it = pics_.begin(); it != pics_.end(); + ++it) { + if ((*it)->pic_order_cnt == poc) { + pics_.erase(it); + UpdatePicPositions(); + return; + } + } + NOTREACHED() << "Missing POC: " << poc; +} + +void H264DPB::DeleteUnused() { + for (H264Picture::Vector::iterator it = pics_.begin(); it != pics_.end();) { + if ((*it)->outputted && !(*it)->ref) + it = pics_.erase(it); + else + ++it; + } + UpdatePicPositions(); +} + +void H264DPB::StorePic(const scoped_refptr<H264Picture>& pic) { + DCHECK_LT(pics_.size(), max_num_pics_); + DVLOG(3) << "Adding PicNum: " << pic->pic_num << " ref: " << (int)pic->ref + << " longterm: " << (int)pic->long_term << " to DPB"; + pic->dpb_position = pics_.size(); + pics_.push_back(pic); +} + +int H264DPB::CountRefPics() { + int ret = 0; + for (size_t i = 0; i < pics_.size(); ++i) { + if (pics_[i]->ref) + ++ret; + } + return ret; +} + +void H264DPB::MarkAllUnusedForRef() { + for (size_t i = 0; i < pics_.size(); ++i) + pics_[i]->ref = false; +} + +scoped_refptr<H264Picture> H264DPB::GetShortRefPicByPicNum(int pic_num) { + for (const auto& pic : pics_) { + if (pic->ref && !pic->long_term && pic->pic_num == pic_num) + return pic; + } + + DVLOG(1) << "Missing short ref pic num: " << pic_num; + return nullptr; +} + +scoped_refptr<H264Picture> H264DPB::GetLongRefPicByLongTermPicNum(int pic_num) { + for (const auto& pic : pics_) { + if (pic->ref && pic->long_term && pic->long_term_pic_num == pic_num) + return pic; + } + + DVLOG(1) << "Missing long term pic num: " << pic_num; + return nullptr; +} + +scoped_refptr<H264Picture> H264DPB::GetLowestFrameNumWrapShortRefPic() { + scoped_refptr<H264Picture> ret; + for (const auto& pic : pics_) { + if (pic->ref && !pic->long_term && + (!ret || pic->frame_num_wrap < ret->frame_num_wrap)) + ret = pic; + } + return ret; +} + +void H264DPB::GetNotOutputtedPicsAppending(H264Picture::Vector* out) { + for (const auto& pic : pics_) { + if (!pic->outputted) + out->push_back(pic); + } +} + +void H264DPB::GetShortTermRefPicsAppending(H264Picture::Vector* out) { + for (const auto& pic : pics_) { + if (pic->ref && !pic->long_term) + out->push_back(pic); + } +} + +void H264DPB::GetLongTermRefPicsAppending(H264Picture::Vector* out) { + for (const auto& pic : pics_) { + if (pic->ref && pic->long_term) + out->push_back(pic); + } +} + +} // namespace media diff --git a/vda/h264_dpb.h b/vda/h264_dpb.h new file mode 100644 index 0000000..703f5e3 --- /dev/null +++ b/vda/h264_dpb.h @@ -0,0 +1,171 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This file contains an implementation of an H.264 Decoded Picture Buffer +// used in H264 decoders. + +#ifndef H264_DPB_H_ +#define H264_DPB_H_ + +#include <stddef.h> + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "h264_parser.h" + +namespace media { + +// A picture (a frame or a field) in the H.264 spec sense. +// See spec at http://www.itu.int/rec/T-REC-H.264 +class H264Picture : public base::RefCounted<H264Picture> { + public: + using Vector = std::vector<scoped_refptr<H264Picture>>; + + enum Field { + FIELD_NONE, + FIELD_TOP, + FIELD_BOTTOM, + }; + + H264Picture(); + + // Values calculated per H.264 specification or taken from slice header. + // See spec for more details on each (some names have been converted from + // CamelCase in spec to Chromium-style names). + int pic_order_cnt_type; + int top_field_order_cnt; + int bottom_field_order_cnt; + int pic_order_cnt; + int pic_order_cnt_msb; + int pic_order_cnt_lsb; + int delta_pic_order_cnt_bottom; + int delta_pic_order_cnt0; + int delta_pic_order_cnt1; + + int pic_num; + int long_term_pic_num; + int frame_num; // from slice header + int frame_num_offset; + int frame_num_wrap; + int long_term_frame_idx; + + H264SliceHeader::Type type; + int nal_ref_idc; + bool idr; // IDR picture? + int idr_pic_id; // Valid only if idr == true. + bool ref; // reference picture? + bool long_term; // long term reference picture? + bool outputted; + // Does memory management op 5 needs to be executed after this + // picture has finished decoding? + bool mem_mgmt_5; + + // Created by the decoding process for gaps in frame_num. + // Not for decode or output. + bool nonexisting; + + Field field; + + // Values from slice_hdr to be used during reference marking and + // memory management after finishing this picture. + bool long_term_reference_flag; + bool adaptive_ref_pic_marking_mode_flag; + H264DecRefPicMarking ref_pic_marking[H264SliceHeader::kRefListSize]; + + // Position in DPB (i.e. index in DPB). + int dpb_position; + + protected: + friend class base::RefCounted<H264Picture>; + virtual ~H264Picture(); + + private: + DISALLOW_COPY_AND_ASSIGN(H264Picture); +}; + +// DPB - Decoded Picture Buffer. +// Stores decoded pictures that will be used for future display +// and/or reference. +class H264DPB { + public: + H264DPB(); + ~H264DPB(); + + void set_max_num_pics(size_t max_num_pics); + size_t max_num_pics() const { return max_num_pics_; } + + // Remove unused (not reference and already outputted) pictures from DPB + // and free it. + void DeleteUnused(); + + // Remove a picture by its pic_order_cnt and free it. + void DeleteByPOC(int poc); + + // Clear DPB. + void Clear(); + + // Store picture in DPB. DPB takes ownership of its resources. + void StorePic(const scoped_refptr<H264Picture>& pic); + + // Return the number of reference pictures in DPB. + int CountRefPics(); + + // Mark all pictures in DPB as unused for reference. + void MarkAllUnusedForRef(); + + // Return a short-term reference picture by its pic_num. + scoped_refptr<H264Picture> GetShortRefPicByPicNum(int pic_num); + + // Return a long-term reference picture by its long_term_pic_num. + scoped_refptr<H264Picture> GetLongRefPicByLongTermPicNum(int pic_num); + + // Return the short reference picture with lowest frame_num. Used for sliding + // window memory management. + scoped_refptr<H264Picture> GetLowestFrameNumWrapShortRefPic(); + + // Append all pictures that have not been outputted yet to the passed |out| + // vector, sorted by lowest pic_order_cnt (in output order). + void GetNotOutputtedPicsAppending(H264Picture::Vector* out); + + // Append all short term reference pictures to the passed |out| vector. + void GetShortTermRefPicsAppending(H264Picture::Vector* out); + + // Append all long term reference pictures to the passed |out| vector. + void GetLongTermRefPicsAppending(H264Picture::Vector* out); + + // Iterators for direct access to DPB contents. + // Will be invalidated after any of Remove* calls. + H264Picture::Vector::iterator begin() { return pics_.begin(); } + H264Picture::Vector::iterator end() { return pics_.end(); } + H264Picture::Vector::const_iterator begin() const { return pics_.begin(); } + H264Picture::Vector::const_iterator end() const { return pics_.end(); } + H264Picture::Vector::const_reverse_iterator rbegin() const { + return pics_.rbegin(); + } + H264Picture::Vector::const_reverse_iterator rend() const { + return pics_.rend(); + } + + size_t size() const { return pics_.size(); } + bool IsFull() const { return pics_.size() == max_num_pics_; } + + // Per H264 spec, increase to 32 if interlaced video is supported. + enum { + kDPBMaxSize = 16, + }; + + private: + void UpdatePicPositions(); + + H264Picture::Vector pics_; + size_t max_num_pics_; + + DISALLOW_COPY_AND_ASSIGN(H264DPB); +}; + +} // namespace media + +#endif // H264_DPB_H_ |