I am using the Media SDK (v3.0.554.34012 Beta4) to encode and am running into a few problems. I hope someone here can help me.
When working with interlaced input (480i and 1080i), the input pictures to the encoder will be deinterlaced frame pictures (i.e. 720x480). I would like the encoder to encode full frames but mark them as interlaced rather than progressive. In essence, I am expecting the Progressive Sequence and progressive frame flags (in the MPEG-2 sequence header and picture header) to be unset and the Top Field First flag to be set/unset as appropriate. However, when I set PicStruct to MFX_PICSTRUCT_FIELD_TFF (or BFF), the encoder seems to be encoding the fields as separate pictures. FYI, I am using the sample_encode app with the arguments as follows:
I could always encode as Progressive and restamp the appropriate bits in the output stream as a post process, but I wanted to make sure there wasn't a way to accomplish this using the SDK.
My other issue might be a bug. In the scenario described above, the GOP header in the output stream only contains correct time codes when encoding interlaced. When PicStruct is MFX_PICSTRUCT_PROGRESSIVE, the GOP header time code appears as 00:00:00:00 in every GOP. Have you seen this behavior?
I'm not sure I fully understand what you are trying to achieve. By using the "-tff" flag with the encode sample you will be encoding an interlaces TFF stream. To test this I used unmodified sample_encode with the same parameters as you used and verified that the stream is of type interlaced TFF and the theProgressive Sequence and progressive frame header flags are set to 0. Can you please clarify a bit more.
Regarding the observed missing timer code in MPEG2 progressive content. I did reproduce this and it may be a bug. We will look into this further. Thanks for reporting this.
Thanks for the info. To clarify, using sample_encode as you describe does produce interlaced fields as output. My situation is as follows: I am using interlaced video as a source (for SD, firstname.lastname@example.org). However, the capture card I am using deinterlaces the video, so the input to the encoder is a sequence of full 720x480 frames at 29.97 fps. I would like to encode these whole (deinterlaced) frames. When using the -tff or -bff options, the encoder breaks the input frames back up into fields and encodes them separately. Thus, the output MPEG-2 stream contains 59.94 half-frames (fields) per second rather than 29.97 full frames.
The only reason I don't encode in progressive mode is that I need the afore-mentioned flags to signify "interlaced" rather than "progressive", as instruction to decoders that the displayed video should be interlaced. We have a fairly large collection of MPEG files from various sources that we use for testing and other purposes, and this seems to be a fairly standard configuration. Let me know if this clears things up.
Did you find out anything in regards to the possible time code bug?
I'm not sure that I understood your case correctly, but please try mfxExtCodingOption.FramePicture = MFX_CODINGOPTION_ON for encoder initialization along with setting mfxVideoParam.mfx.frameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF (or BFF). This way encoder will use the whole frame for coding but stream will be properly marked as interlaced.
If you meant that the input for encoder is essentially progressive (your capture card does actual deinterlacing) and you need to encode it as progressive, only telling decoder to tell renderer to display as interlaced.. then check out the combined display attributes e.g. MFX_PICSTRUCT_PROGRESSIVE| MFX_PICSTRUCT_FIELD_TFF(see mediasdk_man.pdf pp 119-120)
Regarding time code problem - it was confirmed to be a library bug, please expect a fix in Media SDK 3.0 Beta5 which should be available very soon.
to the CBaseEncoder() constructor and set PicStruct to MFX_PICSTRUCT_FIELD_TFF. However, when I try to run a graph, no frames are output from the decoder. If I change PicStruct back to MFX_PICSTRUCT_PROGRESSIVE, this does not happen. Note that the sample_encode project works fine with these settings. Do you know of any reason this should not work in the DirectShow filter?
Good to hear your problem is solved. As for DS MPEG2 Encoder filter, you should modify mfxVideoParam at filter level, not at CBaseEncoder level. Parameters are configured on filter level (read from registry in filter constructor so make sure you add your code later) and then passed to CBaseEncoder.Init in StartStreaming.
Thanks for the feedback. I've tweaked the DS filter code to the point where no settings are being read from the registry or overwritten from those set in BaseEncoder, and I've hard-coded some others to match the values in the sample_encode project. I've traced the code to the point where MFXVideoENCODE_Init() is being called. In the debugger, I've verified that all values in the mfxVideoParam structure being passed (aside from pointer addresses) are equal in both projects. However, the DS filter still fails to output anything when FramePicture = MFX_CODINGOPTION_ON and PicStruct = MFX_PICSTRUCT_FIELD_TFF.
Can you try to debug the Receive method and further to see if there's any problem with EncodeFrameAsync and SyncOperation calls? Any errors returned? Filter failing to output means an error is thrown or the graph hangs or something else? What does your graph look like?
I think I've figured out the issue. The GetRequiredFramesNum() function is called before the mfxExtCodingOption structure is attached. I noticed that QueryIO returns twice the number of necessary frames if I call it later. Since GetAllocatorRequirements() was returning too few buffers, the upstream filter was hanging on GetBuffer() and the encoder stopped receiving input. The change I made was to double the values of nMinFrames and nRecommendedFrames returned by GetRequiresFramesNum() and everything seems to work.
Do you know what, if any, danger there might be in possibly requesting too many buffers (the * 2 is just a quick fix). Thanks again for your help.
Glad to hear you found the reason, great debugging skills :-). I don't see any danger in requesting that many buffers - it's only the question of memory resources. As a quick workaround it's fine. But if you are looking into making this code a product I would suggest to provide proper mfxVideoParam structure to QueryIOSurf called in GetAllocatorRequirements. The fact that current QueryIOSurf implementation requests 2x buffers with params with this particular extCodingOption configuration may change in future versions or may be different for some of the platform specific implementations of MSDK. So it may appear that doubling the output of QueryIOSurf is simply not enough.