| Index: media/gpu/h264_decoder.cc
|
| diff --git a/media/gpu/h264_decoder.cc b/media/gpu/h264_decoder.cc
|
| index e81121737ac6461f46f2434713135499954c63ce..7f4b7e2916a1d5b448f3b7b5b07b8e5b3cc0f8ad 100644
|
| --- a/media/gpu/h264_decoder.cc
|
| +++ b/media/gpu/h264_decoder.cc
|
| @@ -110,55 +110,11 @@ 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)
|
| + curr_pic_ = CreateH264PictureFromSliceHeader(parser_.GetSPS(curr_sps_id_),
|
| + *slice_hdr);
|
| + if (!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 +1136,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_,
|
| + parser_.GetSPS(curr_sps_id_), *slice_hdr)) {
|
| // New picture, so first finish the previous one before processing it.
|
| if (!FinishPrevFrameIfPresent())
|
| return false;
|
| @@ -1439,4 +1354,99 @@ size_t H264Decoder::GetRequiredNumOfPictures() const {
|
| return dpb_.max_num_pics() + kPicsInPipeline;
|
| }
|
|
|
| +// static
|
| +scoped_refptr<H264Picture> H264Decoder::CreateH264PictureFromSliceHeader(
|
| + const H264SPS* sps,
|
| + const H264SliceHeader& slice_hdr) {
|
| + scoped_refptr<H264Picture> pic(new H264Picture());
|
| + 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 nullptr;
|
| + }
|
| +
|
| + 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;
|
| +
|
| + if (!sps)
|
| + return nullptr;
|
| +
|
| + 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 nullptr;
|
| + }
|
| + return pic;
|
| +}
|
| +
|
| +// static
|
| +bool H264Decoder::IsNewPrimaryCodedPicture(scoped_refptr<H264Picture> curr_pic,
|
| + int curr_pps_id,
|
| + const H264SPS* sps,
|
| + const H264SliceHeader& slice_hdr) {
|
| + 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;
|
| +
|
| + 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
|
|
|