Index: media/gpu/h264_decoder.cc |
diff --git a/media/gpu/h264_decoder.cc b/media/gpu/h264_decoder.cc |
index e81121737ac6461f46f2434713135499954c63ce..5b65829a42242860f9b04bd239336303d8dc668e 100644 |
--- a/media/gpu/h264_decoder.cc |
+++ b/media/gpu/h264_decoder.cc |
@@ -110,55 +110,9 @@ bool H264Decoder::InitNonexistingPicture(scoped_refptr<H264Picture> pic, |
} |
bool H264Decoder::InitCurrPicture(const H264SliceHeader* slice_hdr) { |
- DCHECK(curr_pic_.get()); |
- |
- curr_pic_->idr = slice_hdr->idr_pic_flag; |
- if (curr_pic_->idr) |
- curr_pic_->idr_pic_id = slice_hdr->idr_pic_id; |
- |
- if (slice_hdr->field_pic_flag) { |
- curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM |
- : H264Picture::FIELD_TOP; |
- } else { |
- curr_pic_->field = H264Picture::FIELD_NONE; |
- } |
- |
- if (curr_pic_->field != H264Picture::FIELD_NONE) { |
- DVLOG(1) << "Interlaced video not supported."; |
- return false; |
- } |
- |
- curr_pic_->nal_ref_idc = slice_hdr->nal_ref_idc; |
- curr_pic_->ref = slice_hdr->nal_ref_idc != 0; |
- // This assumes non-interlaced stream. |
- curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num; |
- |
- DCHECK_NE(curr_sps_id_, -1); |
- const H264SPS* sps = parser_.GetSPS(curr_sps_id_); |
- if (!sps) |
+ if (!InitPictureFromSliceHeader(curr_sps_id_, parser_, slice_hdr, curr_pic_)) |
return false; |
- curr_pic_->pic_order_cnt_type = sps->pic_order_cnt_type; |
- switch (curr_pic_->pic_order_cnt_type) { |
- case 0: |
- curr_pic_->pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; |
- curr_pic_->delta_pic_order_cnt_bottom = |
- slice_hdr->delta_pic_order_cnt_bottom; |
- break; |
- |
- case 1: |
- curr_pic_->delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt0; |
- curr_pic_->delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt1; |
- break; |
- |
- case 2: |
- break; |
- |
- default: |
- NOTREACHED(); |
- return false; |
- } |
- |
if (!CalculatePicOrderCounts(curr_pic_)) |
return false; |
@@ -1180,53 +1134,12 @@ bool H264Decoder::HandleFrameNumGap(int frame_num) { |
return true; |
} |
-bool H264Decoder::IsNewPrimaryCodedPicture( |
- const H264SliceHeader* slice_hdr) const { |
- if (!curr_pic_) |
- return true; |
- |
- // 7.4.1.2.4, assumes non-interlaced. |
- if (slice_hdr->frame_num != curr_pic_->frame_num || |
- slice_hdr->pic_parameter_set_id != curr_pps_id_ || |
- slice_hdr->nal_ref_idc != curr_pic_->nal_ref_idc || |
- slice_hdr->idr_pic_flag != curr_pic_->idr || |
- (slice_hdr->idr_pic_flag && |
- (slice_hdr->idr_pic_id != curr_pic_->idr_pic_id || |
- // If we have two consecutive IDR slices, and the second one has |
- // first_mb_in_slice == 0, treat it as a new picture. |
- // Per spec, idr_pic_id should not be equal in this case (and we should |
- // have hit the condition above instead, see spec 7.4.3 on idr_pic_id), |
- // but some encoders neglect changing idr_pic_id for two consecutive |
- // IDRs. Work around this by checking if the next slice contains the |
- // zeroth macroblock, i.e. data that belongs to the next picture. |
- slice_hdr->first_mb_in_slice == 0))) |
- return true; |
- |
- const H264SPS* sps = parser_.GetSPS(curr_sps_id_); |
- if (!sps) |
- return false; |
- |
- if (sps->pic_order_cnt_type == curr_pic_->pic_order_cnt_type) { |
- if (curr_pic_->pic_order_cnt_type == 0) { |
- if (slice_hdr->pic_order_cnt_lsb != curr_pic_->pic_order_cnt_lsb || |
- slice_hdr->delta_pic_order_cnt_bottom != |
- curr_pic_->delta_pic_order_cnt_bottom) |
- return true; |
- } else if (curr_pic_->pic_order_cnt_type == 1) { |
- if (slice_hdr->delta_pic_order_cnt0 != curr_pic_->delta_pic_order_cnt0 || |
- slice_hdr->delta_pic_order_cnt1 != curr_pic_->delta_pic_order_cnt1) |
- return true; |
- } |
- } |
- |
- return false; |
-} |
- |
bool H264Decoder::PreprocessCurrentSlice() { |
const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); |
DCHECK(slice_hdr); |
- if (IsNewPrimaryCodedPicture(slice_hdr)) { |
+ if (IsNewPrimaryCodedPicture(curr_pic_, curr_pps_id_, curr_sps_id_, parser_, |
+ slice_hdr)) { |
// New picture, so first finish the previous one before processing it. |
if (!FinishPrevFrameIfPresent()) |
return false; |
@@ -1439,4 +1352,105 @@ size_t H264Decoder::GetRequiredNumOfPictures() const { |
return dpb_.max_num_pics() + kPicsInPipeline; |
} |
+// static |
+bool H264Decoder::InitPictureFromSliceHeader(int curr_sps_id, |
Pawel Osciak
2016/12/20 08:34:22
Perhaps we could instead return a scoped_refptr<H2
emircan
2017/01/03 19:29:00
Done.
|
+ const H264Parser& parser, |
Pawel Osciak
2016/12/20 08:34:22
Perhaps we could pass the SPS directly to the meth
emircan
2017/01/03 19:29:00
Done. Note that I kept param as |const H264SPS* sp
|
+ const H264SliceHeader* slice_hdr, |
+ scoped_refptr<H264Picture> pic) { |
+ DCHECK(pic.get()); |
+ |
+ pic->idr = slice_hdr->idr_pic_flag; |
+ if (pic->idr) |
+ pic->idr_pic_id = slice_hdr->idr_pic_id; |
+ |
+ if (slice_hdr->field_pic_flag) { |
+ pic->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM |
+ : H264Picture::FIELD_TOP; |
+ } else { |
+ pic->field = H264Picture::FIELD_NONE; |
+ } |
+ |
+ if (pic->field != H264Picture::FIELD_NONE) { |
+ DVLOG(1) << "Interlaced video not supported."; |
+ return false; |
+ } |
+ |
+ pic->nal_ref_idc = slice_hdr->nal_ref_idc; |
+ pic->ref = slice_hdr->nal_ref_idc != 0; |
+ // This assumes non-interlaced stream. |
+ pic->frame_num = pic->pic_num = slice_hdr->frame_num; |
+ |
+ DCHECK_NE(curr_sps_id, -1); |
+ const H264SPS* sps = parser.GetSPS(curr_sps_id); |
+ if (!sps) |
+ return false; |
+ |
+ pic->pic_order_cnt_type = sps->pic_order_cnt_type; |
+ switch (pic->pic_order_cnt_type) { |
+ case 0: |
+ pic->pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; |
+ pic->delta_pic_order_cnt_bottom = slice_hdr->delta_pic_order_cnt_bottom; |
+ break; |
+ |
+ case 1: |
+ pic->delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt0; |
+ pic->delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt1; |
+ break; |
+ |
+ case 2: |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+// static |
+bool H264Decoder::IsNewPrimaryCodedPicture(scoped_refptr<H264Picture> curr_pic, |
Pawel Osciak
2016/12/20 08:34:22
const scoped_refptr<>& ?
emircan
2017/01/03 19:29:00
I came across to this in an earlier review that pa
|
+ int curr_pps_id, |
+ int curr_sps_id, |
+ const H264Parser& parser, |
Pawel Osciak
2016/12/20 08:34:22
Here we should be able to also pass an SPS only, w
emircan
2017/01/03 19:29:00
Done.
|
+ const H264SliceHeader* slice_hdr) { |
Pawel Osciak
2016/12/20 08:34:22
Since we are not changing the structure, could we
emircan
2017/01/03 19:29:00
Done.
|
+ if (!curr_pic) |
+ return true; |
+ |
+ // 7.4.1.2.4, assumes non-interlaced. |
+ if (slice_hdr->frame_num != curr_pic->frame_num || |
+ slice_hdr->pic_parameter_set_id != curr_pps_id || |
+ slice_hdr->nal_ref_idc != curr_pic->nal_ref_idc || |
+ slice_hdr->idr_pic_flag != curr_pic->idr || |
+ (slice_hdr->idr_pic_flag && |
+ (slice_hdr->idr_pic_id != curr_pic->idr_pic_id || |
+ // If we have two consecutive IDR slices, and the second one has |
+ // first_mb_in_slice == 0, treat it as a new picture. |
+ // Per spec, idr_pic_id should not be equal in this case (and we should |
+ // have hit the condition above instead, see spec 7.4.3 on idr_pic_id), |
+ // but some encoders neglect changing idr_pic_id for two consecutive |
+ // IDRs. Work around this by checking if the next slice contains the |
+ // zeroth macroblock, i.e. data that belongs to the next picture. |
+ slice_hdr->first_mb_in_slice == 0))) |
+ return true; |
+ |
+ const H264SPS* sps = parser.GetSPS(curr_sps_id); |
+ if (!sps) |
+ return false; |
+ |
+ if (sps->pic_order_cnt_type == curr_pic->pic_order_cnt_type) { |
+ if (curr_pic->pic_order_cnt_type == 0) { |
+ if (slice_hdr->pic_order_cnt_lsb != curr_pic->pic_order_cnt_lsb || |
+ slice_hdr->delta_pic_order_cnt_bottom != |
+ curr_pic->delta_pic_order_cnt_bottom) |
+ return true; |
+ } else if (curr_pic->pic_order_cnt_type == 1) { |
+ if (slice_hdr->delta_pic_order_cnt0 != curr_pic->delta_pic_order_cnt0 || |
+ slice_hdr->delta_pic_order_cnt1 != curr_pic->delta_pic_order_cnt1) |
+ return true; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
} // namespace media |