Doksa
20th June 2007, 10:05
Hey all,
is there some simple way to tell if a VC-1 frame is a keyframe, using only picture header? Maybe someone has figured this out.
Thanks,
Ivan.
Haali
22nd June 2007, 22:41
It's quite simple, but you also need a bit of info from the sequence header to decode frame type. Look at the VC-1 spec or in ffmpeg's VC-1 decoder.
benwaggoner
23rd June 2007, 03:54
This is programatic? To validate that you're getting the correct data, you could use one of the below:
You can try the 15-day trial of Semaphore:
http://www.inlethd.com/encoding/19/17/Semaphore
Or the free WMSnoop:
http://www.sliq.com/default.asp?view=wmsnoop
stegre
27th June 2007, 08:34
I wrote code from scratch to do this for my "ASF2VC1" app, and I've been planning on releasing the entire source to that as well. Below are the snippets that do what you need, but you'd probably want the whole source to see it in context.
The code below covers all the combinations of interlaced vs. progressive and "field encoded" vs. "frame encoded" that are handled by the the VC-1 Advanced Profile. One problem is figuring out which of the 17 resulting frame types (!) are considered "keyframes"! (Answer: "I", "I/I", and "I/P", but not "P/I", nor any of the other 13).
There's a single bit of info - the variable I called "m_bIsInterlaced" - referring to whether the whole file is interlaced or progressive in general, and you do need that - it has to be retrieved from the sequence header, which is what Haali was probably alluding to.
Anyway, I'll paste these snippets so you have something to look at for reference & I hope to post the full source for ASF2VC1 soon.
// if the entire sequence is NOT interlaced, the frame type is in the first four bits.
if (!m_bIsInterlaced)
nFrameType = frmBasedTypeCodes[(pFrameBuf[0] & 0xf0) >> 4];
else
{
// If the entire sequence is IS interlaced, the frame type might still be progressive,
// or might be frame-based interlace, or might be field-based interlaced.
// progressive: acct for the extra bit & use the then same "frmBasedTypeCodes" table, below
if ((pFrameBuf[0] & 0x80) == 0)
nFrameType = frmBasedTypeCodes[(pFrameBuf[0] & 0x78) >> 3];
// we already know bit 7 is set, only check bit 6 now
else if((pFrameBuf[0] & 0x40) == 0) // frame based interlace?
nFrameType = frmBasedTypeCodes[(pFrameBuf[0] & 0x3c) >> 2]; // as above, but acct for 2 extra bits
else // else it's field based interlace - a whole separate animal.
{
// To obtain the [composite] frame type, we use a different table. The code is 3 bits
// fixed length, and we obtain it after accounting for the two "1" bits that got us here.
// Then we get the frame type result from the table "fldBasedTypeCodes", also below.
nFrameType = fldBasedTypeCodes[(pFrameBuf[0] & 0x38) >> 3];
}
}
enum VC1_FRAMETYPE frmBasedTypeCodes[16] =
{
FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, FRMTYPE_FRM_P, // '0xxx'
FRMTYPE_FRM_B, FRMTYPE_FRM_B, FRMTYPE_FRM_B, FRMTYPE_FRM_B, // '10xx'
FRMTYPE_FRM_I, FRMTYPE_FRM_I, // '110x'
FRMTYPE_FRM_BI, // '1110'
FRMTYPE_FRM_D // '1111'
};
enum VC1_FRAMETYPE fldBasedTypeCodes[8] =
{
FRMTYPE_FLD_I_I, FRMTYPE_FLD_I_P, FRMTYPE_FLD_P_I, FRMTYPE_FLD_P_P,
FRMTYPE_FLD_B_B, FRMTYPE_FLD_B_BI, FRMTYPE_FLD_BI_B, FRMTYPE_FLD_BI_BI,
};
// ---------------------------------------------------------------------------------------------------------------
bIsKeyFrame = (nFrameType == FRMTYPE_FRM_I || nFrameType == FRMTYPE_FLD_I_I || nFrameType == FRMTYPE_FLD_I_P))
// ---------------------------------------------------------------------------------------------------------------
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.