There is an interesting problem I've encountered.
When running the sample_encode from the Tutorials on my (fairly moderate) development machine, the number of surfaces suggested to the encoder for running 1080p encoding (i.e. the value of EncRequest.NumFrameSuggested) was equal to 2.
The same code ported to my encoding project, however, the same variable was having the value of 1, even though the resolution of my video is substantially smaller (360p).
Is this expected behaviour, and why ?
By some common sense reasoning, I'd assume that encoding 360p requires substantially less memory than encoding 1080p stream.
What exactly is the run-time reasoning behind granting the available surfaces to the encoder ?
The amount of required surfaces will vary depending on the encoder config. Many parameters impact the selected # of surfaces, such as GOP pattern, AsyncDepth, NumRefFrames etc.
I suspect your encoder config is slightly different between the tow implementations.
As a matter of fact, a specific setting I use appears to be the root cause of the problem that lead me to start this topic.
Let me now try to rephrase my original question:
What is the proper way to set H264 encoder to generate I and P (i.e. no B) frames ?
I've tried to do it by setting the
mfxEncodingParams.mfx.GopRefDist = 1
but noticed that this detail impacts the QueryIOSurf call to return EncRequest.NumFrameSuggested with the value of 1 (which is not enough surfaces to run the encoding (am I right on this ?))
Correct, to encode a stream without B frames you should set mfxEncodingParams.mfx.GopRefDist = 1.
The Media SDK "sample_videoconf" sample has details on how to setup such pipeline. There is also an example in the Media SDK tutorial (http://software.intel.com/en-us/articles/intel-media-sdk-tutorial-simple-6-encode-d3d-lowlatency).
let me reiterate my question:
Is it theoretically possible to get 2 available surfaces with the settings I applied (w = 640, h=360, no B pictures, only I and P) without resorting to D3D or DX11 surfaces ?
If it is, what settings do I need to pay attention to in order for QueryIOSurf() to grant me 2 surfaces ?
The value reported by QueryIOSurf is the minimum number of surfaces you need to be able to use the selected Media SKD component. This is true unless you are running the Media SDK component in an asynchronous fashion, by setting specific AsyncDepth and handling several concurrent tasks (as illustrated in sample_encode). Also, if you are pipelining encode with other component please be aware that you need to have enough surfaces to satisfy both input and output to the components. This is also illustrated in the Media SDK samples and in the Media SDK tutorial samples.
Not sure why you want to ensure exactly 2 surfaces? If QueryIOSurf tells you that one is ok, then there should be no issues.
As much as I am thankful for your effort to answer my questions, I must say, however, that I am a bit perplexed by your last answer.
In every example from the tutorial that I've checked, the integer value (named usually 'nEncSurfNum' or 'numSurfaces') packed in the structure returned from QueryIOSurf( ) call are used as 'max available'. If you look at the rest of the code, the allocated number of surfaces is exactly that much, never more than that.
If it is as you suggest - that the numSurfaces is 'min needed' - it raises a number of questions. More specifically, if we can allocate more surfaces than what is indicated by return value of QueryIOSurf( ) call, then:
Q1) what is the function call which we can use to tell the infrastructure that from now on we will use certain number of surfaces ?
and/or (knowing that surfaces are not unlimited resource)
Q2) what is the function call which we can use to determine the number of currently available surfaces ?
The number of surfaces given by QueryIOSurf should be used for surface allocation as you describe except for the cases when two Media SDK components are pipelined, such as VPP->Encode. For that case the number of input surfaces to encoder (shared with VPP output) is the number of surfaces given by VPP.QueryIOSurf + Encode.QueryIOSurf.
Also, as described in earlier post, if running several concurrent tasks the number of surfaces must be increased by the selected AsyncDepth value.
Both of the above cases are illustrated in the Media SDK "sample_encode" sample and in a couple of the Media SDK tutorial samples (for instance: simple_5_transcode_opaque - async)
Q1) There is no such call. Please use QueryIOSurf as suggested to determine how many surfaces to allocate.
Q2) There is no such call. Surface handling is the responsibility of the application. Application can tell is surface is in use or not by checking surface Data.Locked value as illustrated in all the Media SDK sample code.