@@ -55,6 +55,8 @@ class D3D11H264Picture : public H264Picture {
5555 D3D11PictureBuffer* picture;
5656 size_t picture_index_;
5757
58+ D3D11H264Picture* AsD3D11H264Picture () override { return this ; }
59+
5860 protected:
5961 ~D3D11H264Picture () override ;
6062};
@@ -105,10 +107,12 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
105107
106108 HRESULT hr;
107109 for (;;) {
110+ D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture ();
111+ if (!d3d11_pic)
112+ return DecoderStatus::kFail ;
108113 hr = video_context_->DecoderBeginFrame (
109- video_decoder_.Get (),
110- static_cast <D3D11H264Picture*>(pic.get ())->picture ->output_view ().Get (),
111- 0 , nullptr );
114+ video_decoder_.Get (), d3d11_pic->picture ->output_view ().Get (), 0 ,
115+ nullptr );
112116
113117 if (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING) {
114118 // Hardware is busy. We should make the call again.
@@ -124,7 +128,7 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
124128 }
125129
126130 sps_ = *sps;
127- for (size_t i = 0 ; i < 16 ; i++) {
131+ for (size_t i = 0 ; i < media:: kRefFrameMaxCount ; i++) {
128132 ref_frame_list_[i].bPicEntry = 0xFF ;
129133 field_order_cnt_list_[i][0 ] = 0 ;
130134 field_order_cnt_list_[i][1 ] = 0 ;
@@ -137,8 +141,19 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
137141
138142 int i = 0 ;
139143 for (auto it = dpb.begin (); it != dpb.end (); i++, it++) {
140- D3D11H264Picture* our_ref_pic = static_cast <D3D11H264Picture*>(it->get ());
141- if (!our_ref_pic->ref )
144+ // The DPB is supposed to have a maximum of 16 pictures in it, but there's
145+ // nothing actually stopping it from having more. If we run into this case,
146+ // something is clearly wrong, and we should just fail decoding rather than
147+ // try to sort out which pictures really shouldn't be included.
148+ if (i >= media::kRefFrameMaxCount )
149+ return DecoderStatus::kFail ;
150+
151+ D3D11H264Picture* our_ref_pic = it->get ()->AsD3D11H264Picture ();
152+ // How does a non-d3d11 picture get here you might ask? The decoder
153+ // inserts blank H264Picture objects that we can't use as part of filling
154+ // gaps in frame numbers. If we see one, it's not a reference picture
155+ // anyway, so skip it.
156+ if (!our_ref_pic || !our_ref_pic->ref )
142157 continue ;
143158 ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_ ;
144159 ref_frame_list_[i].AssociatedFlag = our_ref_pic->long_term ;
@@ -285,9 +300,8 @@ void D3D11H264Accelerator::PicParamsFromSliceHeader(
285300}
286301
287302void D3D11H264Accelerator::PicParamsFromPic (DXVA_PicParams_H264* pic_param,
288- scoped_refptr<H264Picture> pic) {
289- pic_param->CurrPic .Index7Bits =
290- static_cast <D3D11H264Picture*>(pic.get ())->picture_index_ ;
303+ D3D11H264Picture* pic) {
304+ pic_param->CurrPic .Index7Bits = pic->picture_index_ ;
291305 pic_param->RefPicFlag = pic->ref ;
292306 pic_param->frame_num = pic->frame_num ;
293307
@@ -320,7 +334,11 @@ DecoderStatus D3D11H264Accelerator::SubmitSlice(
320334 if (!PicParamsFromPPS (&pic_param, pps))
321335 return DecoderStatus::kFail ;
322336 PicParamsFromSliceHeader (&pic_param, slice_hdr);
323- PicParamsFromPic (&pic_param, std::move (pic));
337+
338+ D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture ();
339+ if (!d3d11_pic)
340+ return DecoderStatus::kFail ;
341+ PicParamsFromPic (&pic_param, d3d11_pic);
324342
325343 memcpy (pic_param.RefFrameList , ref_frame_list_,
326344 sizeof pic_param.RefFrameList );
@@ -583,9 +601,8 @@ void D3D11H264Accelerator::Reset() {
583601}
584602
585603bool D3D11H264Accelerator::OutputPicture (scoped_refptr<H264Picture> pic) {
586- D3D11H264Picture* our_pic = static_cast <D3D11H264Picture*>(pic.get ());
587-
588- return client_->OutputResult (our_pic, our_pic->picture );
604+ D3D11H264Picture* our_pic = pic->AsD3D11H264Picture ();
605+ return our_pic && client_->OutputResult (our_pic, our_pic->picture );
589606}
590607
591608void D3D11H264Accelerator::RecordFailure (const std::string& reason,
0 commit comments