summaryrefslogtreecommitdiffstats
path: root/content/common/gpu/media
diff options
context:
space:
mode:
authorposciak@chromium.org <posciak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-07 00:53:50 +0000
committerposciak@chromium.org <posciak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-07 00:53:50 +0000
commit2d8e3e885e59a89056326553121b2fa1c3c00385 (patch)
treee312f4a5ed933ca66fcd541a6f86c90f822c5beb /content/common/gpu/media
parent119e2fe4ad036fbee20658784d429e2bc00c6588 (diff)
downloadchromium_src-2d8e3e885e59a89056326553121b2fa1c3c00385.zip
chromium_src-2d8e3e885e59a89056326553121b2fa1c3c00385.tar.gz
chromium_src-2d8e3e885e59a89056326553121b2fa1c3c00385.tar.bz2
VAVDA: Calculate number of required pictures depending on codec level.
Instead of always allocating maximum required number of pictures (16) by H264 spec, check the codec level and calculate the required number of pictures (DPB size). Also, remove check for frame_mbs_only_flag, which was not correct and is handled differently elsewhere. BUG=136376 TEST=videotestmatrix Review URL: https://chromiumcodereview.appspot.com/12209030 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181123 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common/gpu/media')
-rw-r--r--content/common/gpu/media/h264_dpb.cc11
-rw-r--r--content/common/gpu/media/h264_dpb.h8
-rw-r--r--content/common/gpu/media/vaapi_h264_decoder.cc64
-rw-r--r--content/common/gpu/media/vaapi_h264_decoder.h15
4 files changed, 76 insertions, 22 deletions
diff --git a/content/common/gpu/media/h264_dpb.cc b/content/common/gpu/media/h264_dpb.cc
index a512644..f97ca3d 100644
--- a/content/common/gpu/media/h264_dpb.cc
+++ b/content/common/gpu/media/h264_dpb.cc
@@ -10,13 +10,20 @@
namespace content {
-H264DPB::H264DPB() {}
+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, kDPBMaxSize);
+ max_num_pics_ = max_num_pics;
+ if (pics_.size() > max_num_pics_)
+ pics_.resize(max_num_pics_);
+}
+
void H264DPB::RemoveByPOC(int poc) {
for (Pictures::iterator it = pics_.begin(); it != pics_.end(); ++it) {
if ((*it)->pic_order_cnt == poc) {
@@ -37,7 +44,7 @@ void H264DPB::RemoveUnused() {
}
void H264DPB::StorePic(H264Picture* pic) {
- DCHECK_LT(pics_.size(), kDPBMaxSize);
+ 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";
pics_.push_back(pic);
diff --git a/content/common/gpu/media/h264_dpb.h b/content/common/gpu/media/h264_dpb.h
index d1ef3be..17cc88d 100644
--- a/content/common/gpu/media/h264_dpb.h
+++ b/content/common/gpu/media/h264_dpb.h
@@ -68,6 +68,9 @@ class H264DPB {
H264DPB();
~H264DPB();
+ void set_max_num_pics(size_t max_num_pics);
+ size_t max_num_pics() { return max_num_pics_; }
+
// Remove unused (not reference and already outputted) pictures from DPB.
void RemoveUnused();
@@ -115,13 +118,14 @@ class H264DPB {
Pictures::reverse_iterator rend() { return pics_.rend(); }
size_t size() const { return pics_.size(); }
- bool IsFull() const { return pics_.size() == kDPBMaxSize; }
+ bool IsFull() const { return pics_.size() == max_num_pics_; }
// Per H264 spec, increase to 32 if interlaced video is supported.
- enum { kDPBMaxSize = 16 };
+ enum { kDPBMaxSize = 16, };
private:
Pictures pics_;
+ size_t max_num_pics_;
DISALLOW_COPY_AND_ASSIGN(H264DPB);
};
diff --git a/content/common/gpu/media/vaapi_h264_decoder.cc b/content/common/gpu/media/vaapi_h264_decoder.cc
index 02df1aa..4f26d47 100644
--- a/content/common/gpu/media/vaapi_h264_decoder.cc
+++ b/content/common/gpu/media/vaapi_h264_decoder.cc
@@ -1571,7 +1571,7 @@ bool VaapiH264Decoder::ModifyReferencePicList(H264SliceHeader *slice_hdr,
ref_pic_listx = &ref_pic_list1_;
}
- DCHECK_GT(num_ref_idx_lX_active_minus1, 0);
+ DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
// Spec 8.2.4.3:
// Reorder pictures on the list in a way specified in the stream.
@@ -2035,16 +2035,35 @@ bool VaapiH264Decoder::FinishPicture() {
return true;
}
+static int LevelToMaxDpbMbs(int level) {
+ // See table A-1 in spec.
+ switch (level) {
+ case 10: return 396;
+ case 11: return 900;
+ case 12: // fallthrough
+ case 13: // fallthrough
+ case 20: return 2376;
+ case 21: return 4752;
+ case 22: // fallthrough
+ case 30: return 8100;
+ case 31: return 18000;
+ case 32: return 20480;
+ case 40: // fallthrough
+ case 41: return 32768;
+ case 42: return 34816;
+ case 50: return 110400;
+ case 51: // fallthrough
+ case 52: return 184320;
+ default:
+ DVLOG(1) << "Invalid codec level (" << level << ")";
+ return 0;
+ }
+}
+
bool VaapiH264Decoder::ProcessSPS(int sps_id) {
const H264SPS* sps = parser_.GetSPS(sps_id);
DCHECK(sps);
- if (sps->frame_mbs_only_flag == 0) {
- // Fields/interlaced video not supported.
- DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
- return false;
- }
-
if (sps->gaps_in_frame_num_value_allowed_flag) {
DVLOG(1) << "Gaps in frame numbers not supported";
return false;
@@ -2052,11 +2071,21 @@ bool VaapiH264Decoder::ProcessSPS(int sps_id) {
curr_sps_id_ = sps->seq_parameter_set_id;
- // Calculate picture height/width (spec 7.4.2.1.1, 7.4.3).
- int width = 16 * (sps->pic_width_in_mbs_minus1 + 1);
- int height = 16 * (2 - sps->frame_mbs_only_flag) *
+ // Calculate picture height/width in macroblocks and pixels
+ // (spec 7.4.2.1.1, 7.4.3).
+ int width_mb = sps->pic_width_in_mbs_minus1 + 1;
+ int height_mb = (2 - sps->frame_mbs_only_flag) *
(sps->pic_height_in_map_units_minus1 + 1);
+ int width = 16 * width_mb;
+ int height = 16 * height_mb;
+
+ DVLOG(1) << "New picture size: " << width << "x" << height;
+ if (width == 0 || height == 0) {
+ DVLOG(1) << "Invalid picture size!";
+ return false;
+ }
+
if ((pic_width_ != -1 || pic_height_ != -1) &&
(width != pic_width_ || height != pic_height_)) {
DVLOG(1) << "Picture size changed mid-stream";
@@ -2065,11 +2094,21 @@ bool VaapiH264Decoder::ProcessSPS(int sps_id) {
pic_width_ = width;
pic_height_ = height;
- DVLOG(1) << "New picture size: " << pic_width_ << "x" << pic_height_;
max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
+ int level = sps->level_idc;
+ int max_dpb_mbs = LevelToMaxDpbMbs(level);
+ if (max_dpb_mbs == 0)
+ return false;
+
+ size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
+ static_cast<int>(H264DPB::kDPBMaxSize));
+ DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
+
+ dpb_.set_max_num_pics(max_dpb_size);
+
return true;
}
@@ -2300,9 +2339,8 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::DecodeOneFrame(int32 input_id) {
}
}
-// static
size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
- return kNumReqPictures;
+ return dpb_.max_num_pics() + kPicsInPipeline;
}
// static
diff --git a/content/common/gpu/media/vaapi_h264_decoder.h b/content/common/gpu/media/vaapi_h264_decoder.h
index ce6ef80..8abb28b 100644
--- a/content/common/gpu/media/vaapi_h264_decoder.h
+++ b/content/common/gpu/media/vaapi_h264_decoder.h
@@ -141,7 +141,7 @@ class VaapiH264Decoder {
// Return the number of output pictures required for decoding.
// Valid after a successful DecodeInitial().
- static size_t GetRequiredNumOfPictures();
+ size_t GetRequiredNumOfPictures();
// Do any necessary initialization before the sandbox is enabled.
static void PreSandboxInitialization();
@@ -151,14 +151,16 @@ class VaapiH264Decoder {
static bool PostSandboxInitialization();
private:
- // We need to keep at least kDPBMaxSize pictures in DPB for
+ // We need to keep at most kDPBMaxSize pictures in DPB for
// reference/to display later and an additional one for the one currently
// being decoded. We also ask for some additional ones since VDA needs
// to accumulate a few ready-to-output pictures before it actually starts
// displaying and giving them back. +2 instead of +1 because of subjective
// smoothness improvement during testing.
- enum { kNumReqPictures = H264DPB::kDPBMaxSize +
- media::limits::kMaxVideoFrames + 2 };
+ enum {
+ kPicsInPipeline = media::limits::kMaxVideoFrames + 2,
+ kMaxNumReqPictures = H264DPB::kDPBMaxSize + kPicsInPipeline,
+ };
// Internal state of the decoder.
enum State {
@@ -349,7 +351,7 @@ class VaapiH264Decoder {
bool va_context_created_;
// Allocated VASurfaces.
- VASurfaceID va_surface_ids_[kNumReqPictures];
+ VASurfaceID va_surface_ids_[kMaxNumReqPictures];
// Called by decoder when a picture should be outputted.
OutputPicCB output_pic_cb_;
@@ -360,6 +362,9 @@ class VaapiH264Decoder {
// PicOrderCount of the previously outputted frame.
int last_output_poc_;
+ // Maximum size of DPB required by codec level.
+ int max_dpb_size_;
+
// Has static initialization of pre-sandbox components completed successfully?
static bool pre_sandbox_init_done_;