Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply RFC 7741 for VP8 #178

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Apply RFC 7741 for VP8
L: TL0PICIDX present. When set to 1, the TL0PICIDX MUST be present
and specified as below, and the T bit MUST be set to 1.
Otherwise, TL0PICIDX MUST NOT be present.

Add Y bit and KEYIDX value to be obtain
Add Vp8 Key Frame validation
Get Width and Height and their scaling values from Vp8 Payload Header
lem21h committed Jan 8, 2020

Verified

This commit was signed with the committer’s verified signature.
kyteinsky Anupam Kumar
commit 2587b8f4c0a6aa083708a266a8a71bd4e66ad574
Original file line number Diff line number Diff line change
@@ -121,14 +121,30 @@ public static class VP8PayloadDescriptor
private static final byte N_BIT = (byte) 0x20;

/**
* Gets the temporal layer index (TID), if that's set.
* The bitmask for the temporal-layer index
*/
private static final byte TID_MASK = (byte) 0xC0;

/**
* Y bit from the TID/Y/KEYIDX extension byte.
*/
private static final byte Y_BIT = (byte) 0x20;

/**
* The bitmask for the temporal key frame index
*/
private static final byte KEYIDX_MASK = (byte) 0x1F;

/**
* Gets the TID/Y/KEYIDX extension byte if available
*
* @param buf the byte buffer that holds the VP8 packet.
* @param off the offset in the byte buffer where the VP8 packet starts.
* @param len the length of the VP8 packet.
* @return the temporal layer index (TID), if that's set, -1 otherwise.
*
* @return the TID/Y/KEYIDX extension byte, if that's set, -1 otherwise.
*/
public static int getTemporalLayerIndex(byte[] buf, int off, int len)
private static byte getTidYKeyIdxExtensionByte(byte[] buf, int off, int len)
{
if (buf == null || buf.length < off + len || len < 2)
{
@@ -146,7 +162,54 @@ public static int getTemporalLayerIndex(byte[] buf, int off, int len)
return -1;
}

return (buf[off + sz - 1] & 0xc0) >> 6;
return (byte) (buf[off + sz - 1] & 0xFF);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the & 0xFF do here? This is a byte.

Copy link
Author

@lem21h lem21h Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sure that if regular value of the byte is greater than 127, then it won't change to negative values when converting to integer and back to byte

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But doesn't it convert to negative anyway when you cast to byte?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, fixed

}

/**
* Gets the temporal layer index (TID), if that's set.
*
* @param buf the byte buffer that holds the VP8 packet.
* @param off the offset in the byte buffer where the VP8 packet starts.
* @param len the length of the VP8 packet.
* @return the temporal layer index (TID), if that's set, -1 otherwise.
*/
public static int getTemporalLayerIndex(byte[] buf, int off, int len)
{
byte tidYKeyIdxByte = getTidYKeyIdxExtensionByte(buf, off, len);

return tidYKeyIdxByte != -1 && (buf[off+1] & T_BIT) != 0 ?(tidYKeyIdxByte & TID_MASK) >> 6 : tidYKeyIdxByte;
}

/**
* Gets the 1 layer sync bit (Y BIT), if that's set.
*
* @param buf the byte buffer that holds the VP8 packet.
* @param off the offset in the byte buffer where the VP8 packet starts.
* @param len the length of the VP8 packet.
*
* @return the 1 layer sync bit (Y BIT), if that's set, -1 otherwise.
*/
public static int getFirstLayerSyncBit(byte[] buf, int off, int len)
{
byte tidYKeyIdxByte = getTidYKeyIdxExtensionByte(buf, off, len);

return tidYKeyIdxByte != -1 ? (tidYKeyIdxByte & Y_BIT) >> 5 : tidYKeyIdxByte;
}

/**
* Gets the temporal key frame index (KEYIDX), if that's set.
*
* @param buf the byte buffer that holds the VP8 packet.
* @param off the offset in the byte buffer where the VP8 packet starts.
* @param len the length of the VP8 packet.
*
* @return the temporal key frame index (KEYIDX), if that's set, -1 otherwise.
*/
public static int getTemporalKeyFrameIndex(byte[] buf, int off, int len)
{
byte tidYKeyIdxByte = getTidYKeyIdxExtensionByte(buf, off, len);

return tidYKeyIdxByte != -1 && (buf[off+1] & K_BIT) != 0 ? (tidYKeyIdxByte & KEYIDX_MASK) : tidYKeyIdxByte;
}

/**
@@ -202,7 +265,7 @@ public static boolean setTemporalLayerIndex(byte[] buf, int off, int len, int ti
public static byte[] create(boolean startOfPartition)
{
byte[] pd = new byte[1];
pd[0] = startOfPartition ? (byte) 0x10 : 0;
pd[0] = startOfPartition ? S_BIT : 0;
return pd;
}

@@ -252,7 +315,8 @@ public static int getSize(byte[] input, int offset, int length)
if ((input[offset + 2] & M_BIT) != 0)
size++;
}
if ((input[offset + 1] & L_BIT) != 0)
// if L_BIT is set then T_BIT also has to be set according to RFC 7741
if ((input[offset+1] & (L_BIT | T_BIT)) != 0)
size++;
if ((input[offset + 1] & (T_BIT | K_BIT)) != 0)
size++;
@@ -564,13 +628,57 @@ public static class VP8KeyframeHeader
//
// 16 bits : (2 bits Horizontal Scale << 14) | Width (14 bits)
// 16 bits : (2 bits Vertical Scale << 14) | Height (14 bits)
public static final byte[] START_CODES = {(byte) 0x9D, 0x01, 0x2A};

/**
* @return True, if VP8 Payload contains start codes of a keyframe, otherwise false.
*/
public static boolean validate(byte[] buf, int off)
JonathanLennox marked this conversation as resolved.
Show resolved Hide resolved
{
if (buf.length - off < 5)
{
return false;
}
for (int i = 0; i < START_CODES.length; i++)
{
if ((buf[off + 2 + i] - START_CODES[i]) != 0)
{
return false;
}
}
return true;
}

/**
* @return the height of this instance.
*/
public static int getHeight(byte[] buf, int off)
{
return (((buf[off + 6] & 0xff) << 8) | buf[off + 5] & 0xff) & 0x3fff;
return (((buf[off + 6] & 0x3F) << 8) | buf[off + 5] & 0xFF);
}

/**
* @return the height scaling of this instance.
*/
public static int getHeightScaling(byte[] buf, int off)
{
return (buf[off + 6] & 0xC0) >> 6;
}

/**
* @return the width of this instance.
*/
public static int getWidth(byte[] buf, int off)
{
return (((buf[off + 8] & 0x3F) << 8) | buf[off + 7] & 0xFF);
}

/**
* @return the width scaling of this instance.
*/
public static int getWidthScaling(byte[] buf, int off)
{
return (buf[off + 8] & 0xC0) >> 6;
}
}
}