intel / libvpl

Intel® Video Processing Library (Intel® VPL) API, dispatcher, and examples
https://intel.github.io/libvpl/
MIT License
262 stars 80 forks source link

Software implementaion of MFXVideoDECODE_DecodeHeader doesn't fill mfxVideoParam structure if bitstream contains only single HEVC I-frame. #15

Closed oliort closed 2 years ago

oliort commented 3 years ago

I used hello-decvpp openVPL example on some raw hevc-compressed videos from the internet in softaware mode (using -sw command line option) and it worked fine so i proceeded with implementation of my HEVC-decoding application, expecting the software decoder to work well. I wrote everything like in that hello-decvpp example except that I receive compressed video frames from the internet and put discrete single I-frames in AnnexB bitstream format (skipping P-frames, which i don't need) to the bitstream with next code (executed each I-frame):

mfxBitstream bitstream = {};
bitstream.MaxLength = bitstream.DataLength = myIFrameSizeInBytes;
bitstream.Data = myIFrameData;
bitstream.CodecId = MFX_CODEC_HEVC;

Then I try to read video parameters (like width, height and fourCC) from the I-frame header with:

m_videoParams = {};
m_videoParams.mfx.CodecId = MFX_CODEC_HEVC;
m_videoParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
sts = MFXVideoDECODE_DecodeHeader(m_session, pBitstream, &m_videoParams);

I get sts == MFX_ERR_NONE but most of the fields of m_videoParams (like .mfx.FrameInfo.Height, etc.) remain equal zero. I noticed that if i keep the first I-frame in the bitstream and then append the next one, after the second frame arrives and bitstream contains both of them (with MaxLength & DataLength fields = sum of sizes of two frames in bytes), function MFXVideoDECODE_DecodeHeader behaves as expected and fills in the needed fields of mfxVideoParam structure.

I played with it a little bit more and discovered that actualy what is enough is just to append to the bitstream 8 bytes in the end after the single I-frame (as if a next VPS NAL-unit piece resides there):

0x00 0x00 0x00 0x01 0x40 0x01 0x0c 0x01

First I though that maybe the function expects for more than 1 frame to be in the bitstream, but then i discovered that hardware implementation has no such problem and just an I-frame may be passed there in the bitstream (without magical 8 bytes) to get needed video parameters in the mfxVideoParam structure. Also it's strange that i can't extract video parameters from single I-frame with all its SPS,PPS and VPS as those should contain the info.

My software implementation version: 2.2 My hardware implementation version: 1.33 (d3d9+hw) My CPU: Intel Core I5-7400, drivers updated

oliort commented 3 years ago

I also tried MFX_BITSTREAM_COMPLETE_FRAME and/or MFX_BITSTREAM_EOS but that didn't help.

oliort commented 3 years ago

I found out that actualy mfxVideoParam I get that way does not work. Passing it as an argument to MFXVideoDECODE_VPP_Init() makes it return undocumented MFX_ERR_NOT_INITIALIZED (-8) value.

ying2guo commented 2 years ago

Hi Oliort, Thanks for contacting us regarding your use case. We investigated based on your message and found a workaround that may help.

Please try using "bitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME" flag as shown in following code snippet:

// Prepare input bitstream and start decoding
// we tested by setting this value to 4231 base on the size of the first I-Frame of our test content    
// cars_320x240.h265. This value should be evaluated accurately to reflect the size of the first frame.
bitstream.MaxLength = myIFrameSizeInBytes;
bitstream.Data = (mfxU8 *)calloc(bitstream.MaxLength, sizeof(mfxU8));

// add this line as workaround
bitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
// before this line
VERIFY(bitstream.Data, "Not able to allocate input buffer");

[...]

// After following line executes, &mfxDecParams.mfx.FrameInfo shows dimensions FourCC and etc values.
sts = MFXVideoDECODE_DecodeHeader(session, &bitstream, &mfxDecParams);