/*
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "vc1Parser.h"
#include "common/log.h"
#include "common/common_def.h"
#include <cstring>
#include <cassert>
#define READ(f) \
do { \
if (!br->readT(f)) { \
ERROR("failed to read %s", #f); \
return false; \
} \
} while (0)
#define READ_BITS(f, bits) \
do { \
if (!br->readT(f, bits)) { \
ERROR("failed to read %d bits to %s", bits, #f); \
return false; \
} \
} while (0)
#define SKIP(bits) \
do { \
if (!br->skip(bits)) { \
ERROR("failed to skip %d bits", bits); \
return false; \
} \
} while (0)
#define PEEK(f, bits) \
do { \
if (!br->peek(f, bits)) { \
ERROR("failed to peek %d bits to %s", bits, #f); \
return false; \
} \
} while (0)
namespace YamiParser {
namespace VC1 {
/* Table 36: PQINDEX to PQUANT/Quantizer Translation*/
static const uint8_t QuantizerTranslationTable[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31
};
/* Table 69: IMODE VLC Code table */
static const VLCTable ImodeVLCTable[7] = {
{ 2, 2 }, { 3, 2 }, { 2, 3 },
{ 3, 3 }, { 1, 3 }, { 1, 4 }, { 0, 4 }
};
/* Table 81: Code table for 3x2 and 2x3 tiles */
static const VLCTable Norm6VLCTable[64] = {
{ 1, 1 },
{ 2, 4 },
{ 3, 4 },
{ 0, 8 },
{ 4, 4 },
{ 1, 8 },
{ 2, 8 },
{ (2 << 5) | 7, (5 + 5) },
{ 5, 4 },
{ 3, 8 },
{ 4, 8 },
{ (2 << 5) | 11, (5 + 5) },
{ 5, 8 },
{ (2 << 5) | 13, (5 + 5) },
{ (2 << 5) | 14, (5 + 5) },
{ (3 << 8) | 14, (5 + 8) },
{ 6, 4 },
{ 6, 8 },
{ 7, 8 },
{ (2 << 5) | 19, (5 + 5) },
{ 8, 8 },
{ (2 << 5) | 21, (5 + 5) },
{ (2 << 5) | 22, (5 + 5) },
{ (3 << 8) | 13, (5 + 8) },
{ 9, 8 },
{ (2 << 5) | 25, (5 + 5) },
{ (2 << 5) | 26, (5 + 5) },
{ (3 << 8) | 12, (5 + 8) },
{ (2 << 5) | 28, (5 + 5) },
{ (3 << 8) | 11, (5 + 8) },
{ (3 << 8) | 10, (5 + 8) },
{ (3 << 4) | 7, (5 + 4) },
{ 7, 4 },
{ 10, 8 },
{ 11, 8 },
{ (2 << 5) | 3, (5 + 5) },
{ 12, 8 },
{ (2 << 5) | 5, (5 + 5) },
{ (2 << 5) | 6, (5 + 5) },
{ (3 << 8) | 9, (5 + 8) },
{ 13, 8 },
{ (2 << 5) | 9, (5 + 5) },
{ (2 << 5) | 10, (5 + 5) },
{ (3 << 8) | 8, (5 + 8) },
{ (2 << 5) | 12, (5 + 5) },
{ (3 << 8) | 7, (5 + 8) },
{ (3 << 8) | 6, (5 + 8) },
{ (3 << 4) | 6, (5 + 4) },
{ 14, 8 },
{ (2 << 5) | 17, (5 + 5) },
{ (2 << 5) | 18, (5 + 5) },
{ (3 << 8) | 5, (5 + 8) },
{ (2 << 5) | 20, (5 + 5) },
{ (3 << 8) | 4, (5 + 8) },
{ (3 << 8) | 3, (5 + 8) },
{ (3 << 4) | 5, (5 + 4) },
{ (2 << 5) | 24, (5 + 5) },
{ (3 << 8) | 2, (5 + 8) },
{ (3 << 8) | 1, (5 + 8) },
{ (3 << 4) | 4, (5 + 4) },
{ (3 << 8) | 0, (5 + 8) },
{ (3 << 4) | 3, (5 + 4) },
{ (3 << 4) | 2, (5 + 4) },
{ (3 << 1) | 1, (5 + 1) }
};
static const FrameType FrameTypeTable[2][8] = {
{
FRAME_I, FRAME_I, FRAME_P, FRAME_P,
FRAME_B, FRAME_B, FRAME_BI, FRAME_BI
},
{
FRAME_P, FRAME_B, FRAME_I, FRAME_BI,
FRAME_SKIPPED
},
};
/* Table 40: BFRACTION VLC Table */
static const VLCTable BFractionVLCTable[] = {
{0x00, 3}, {0x01, 3},
{0x02, 3}, {0x02, 3},
{0x04, 3}, {0x05, 3},
{0x06, 3}, {0x70, 7},
{0x71, 7}, {0x72, 7},
{0x73, 7}, {0x74, 7},
{0x75, 7}, {0x76, 7},
{0x77, 7}, {0x78, 7},
{0x79, 7}, {0x7a, 7},
{0x7b, 7}, {0x7c, 7},
{0x7d, 7}, {0x7e, 7},
{0x7f, 7}
};
Parser::Parser()
{
memset(&m_seqHdr, 0, sizeof(m_seqHdr));
memset(&m_entryPointHdr, 0, sizeof(m_entryPointHdr));
}
Parser::~Parser()
{
}
bool Parser::parseCodecData(uint8_t* data, uint32_t size)
{
int32_t offset;
offset = searchStartCode(data, size);
if (offset < 0) {
if (!parseSequenceHeader(data, size))
return false;
}
else {
while (1) {
data += (offset + 4);
size -= (offset + 4);
if (data[-1] == 0xF) {
if (!parseSequenceHeader(data, size))
return false;
}
else if (data[-1] == 0xE) {
if (!parseEntryPointHeader(data, size))
return false;
}
offset = searchStartCode(data, size);
if (offset < 0)
break;
}
}
return true;
}
bool Parser::parseFrameHeader(uint8_t*& data, uint32_t& size)
{
bool ret = false;
m_mbWidth = (m_seqHdr.coded_width + 15) >> 4;
m_mbHeight = (m_seqHdr.coded_height + 15) >> 4;
mallocBitPlanes();
memset(&m_frameHdr, 0, sizeof(m_frameHdr));
if (!convertToRbdu(data, size))
return false;
BitReader bitReader(&m_rbdu[0], m_rbdu.size());
if (m_seqHdr.profile != PROFILE_ADVANCED) {
ret = parseFrameHeaderSimpleMain(&bitReader);
}
else {
/* support advanced profile */
ret = parseFrameHeaderAdvanced(&bitReader);
}
m_frameHdr.macroblock_offset = bitReader.getPos();
return ret;
}
int32_t Parser::searchStartCode(uint8_t* data, uint32_t size)
{
uint8_t* pos;
const uint8_t startCode[] = { 0x00, 0x00, 0x01 };
pos = std::search(data, data + size, startCode, startCode + 3);
return (pos == data + size) ? (-1) : (pos - data);
}
bool Parser::convertToRbdu(uint8_t*& data, uint32_t& size)
{
uint8_t* pos;
int32_t offset, i = 0;
const uint8_t startCode[] = { 0x00, 0x00, 0x03 };
if (m_seqHdr.profile == PROFILE_ADVANCED) {
while (1) {
/*skip for ununsed bdu types*/
/*data and size are input and output parameters*/
offset = searchStartCode(data, size);
if (offset >= 0) {
data += (offset + 4);
size -= (offset + 4);
}
if ((offset < 0) || (data[-1] == 0xD))
break;
}
if (offset < 0) {
size = 0;
return false;
}
}
m_rbdu.clear();
/*extraction of rbdu from ebdu*/
while (1) {
pos = std::search(data + i, data + size, startCode, startCode + 3);
if (pos == data + size) {
m_rbdu.insert(m_rbdu.end(), data + i, pos);
break;
}
if (pos[3] <= 0x03) {
m_rbdu.insert(m_rbdu.end(), data + i, pos + 2);
}
else {
m_rbdu.insert(m_rbdu.end(), data + i, pos + 3);
}
i = pos - data + 3;
}
return (size > 0);
}
/*Table 3: Sequence layer bitstream for Advanced Profile*/
/*Table 263: Sequence Header Data Structure STRUCT_C for Simple and Main Profiles*/
/*Table 264: Sequence Header Data Structure STRUCT_C for Advanced Profiles*/
bool Parser::parseSequenceHeader(const uint8_t* data, uint32_t size)
{
uint32_t i;
BitReader bitReader(data, size);
BitReader* br = &bitReader;
READ_BITS(m_seqHdr.profile, 2);
if (m_seqHdr.profile != PROFILE_ADVANCED) {
/* skip reserved bits */
SKIP(2);
READ_BITS(m_seqHdr.frmrtq_postproc, 3);
READ_BITS(m_seqHdr.bitrtq_postproc, 5);
READ(m_seqHdr.loop_filter);
/* skip reserved bits */
SKIP(1);
READ(m_seqHdr.multires);
/* skip reserved bits */
SKIP(1);
READ(m_seqHdr.fastuvmc);
READ(m_seqHdr.extended_mv);
READ_BITS(m_seqHdr.dquant, 2);
READ(m_seqHdr.variable_sized_transform_flag);
/* skip reserved bits */
SKIP(1);
READ(m_seqHdr.overlap);
READ(m_seqHdr.syncmarker);
READ(m_seqHdr.rangered);
READ_BITS(m_seqHdr.max_b_frames, 3);
READ_BITS(m_seqHdr.quantizer, 2);
READ(m_seqHdr.finterpflag);
}
else {
READ_BITS(m_seqHdr.level, 3);
READ_BITS(m_seqHdr.colordiff_format, 2);
READ_BITS(m_seqHdr.frmrtq_postproc, 3);
READ_BITS(m_seqHdr.bitrtq_postproc, 5);
READ(m_seqHdr.postprocflag);
uint16_t tmp;
READ_BITS(tmp, 12);
m_seqHdr.coded_width = (tmp + 1) << 1;
READ_BITS(tmp, 12);
m_seqHdr.coded_height = (tmp + 1) << 1;
READ(m_seqHdr.pulldown);
READ(m_seqHdr.interlace);
READ(m_seqHdr.tfcntrflag);
READ(m_seqHdr.finterpflag);
/* skip reserved bits */
SKIP(1);
READ(m_seqHdr.psf);
READ(m_seqHdr.display_ext);
if (m_seqHdr.display_ext) {
READ_BITS(m_seqHdr.disp_horiz_size, 14);
m_seqHdr.disp_horiz_size++;
READ_BITS(m_seqHdr.disp_vert_size, 14);
m_seqHdr.disp_vert_size++;
READ(m_seqHdr.aspect_ratio_flag);
if (m_seqHdr.aspect_ratio_flag) {
READ_BITS(m_seqHdr.aspect_ratio, 4);
if (m_seqHdr.aspect_ratio == 15) {
READ(m_seqHdr.aspect_horiz_size);
READ(m_seqHdr.aspect_vert_size);
}
}
READ(m_seqHdr.framerate_flag);
if (m_seqHdr.framerate_flag) {
READ(m_seqHdr.framerateind);
if (m_seqHdr.framerateind == 0) {
READ(m_seqHdr.frameratenr);
READ_BITS(m_seqHdr.frameratedr, 4);
}
else {
READ(m_seqHdr.framerateexp);
}
}
READ(m_seqHdr.color_format_flag);
if (m_seqHdr.color_format_flag) {
READ(m_seqHdr.color_prim);
READ(m_seqHdr.transfer_char);
READ(m_seqHdr.matrix_coef);
}
}
READ(m_seqHdr.hrd_param_flag);
/*Table 13: Syntax elements for HRD_PARAM structure*/
if (m_seqHdr.hrd_param_flag) {
READ_BITS(m_seqHdr.hrd_param.hrd_num_leaky_buckets, 5);
READ_BITS(m_seqHdr.hrd_param.bit_rate_exponent, 4);
READ_BITS(m_seqHdr.hrd_param.buffer_size_exponent, 4);
for (i = 0; i < m_seqHdr.hrd_param.hrd_num_leaky_buckets; i++) {
READ(m_seqHdr.hrd_param.hrd_rate[i]);
READ(m_seqHdr.hrd_param.hrd_buffer[i]);
}
}
}
return true;
}
/*Table 14: Entry-point layer bitstream for Advanced Profile*/
bool Parser::parseEntryPointHeader(const uint8_t* data, uint32_t size)
{
uint8_t i;
BitReader bitReader(data, size);
BitReader* br = &bitReader;
READ(m_entryPointHdr.broken_link);
READ(m_entryPointHdr.closed_entry);
READ(m_entryPointHdr.panscan_flag);
READ(m_entryPointHdr.reference_distance_flag);
READ(m_entryPointHdr.loopfilter);
READ(m_entryPointHdr.fastuvmc);
READ(m_entryPointHdr.extended_mv);
READ_BITS(m_entryPointHdr.dquant, 2);
READ(m_entryPointHdr.variable_sized_transform_flag);
READ(m_entryPointHdr.overlap);
READ_BITS(m_entryPointHdr.quantizer, 2);
if (m_seqHdr.hrd_param_flag) {
for (i = 0; i < m_seqHdr.hrd_param.hrd_num_leaky_buckets; i++)
READ(m_entryPointHdr.hrd_full[i]);
}
READ(m_entryPointHdr.coded_size_flag);
if (m_entryPointHdr.coded_size_flag) {
READ_BITS(m_entryPointHdr.coded_width, 12);
m_entryPointHdr.coded_width = (m_entryPointHdr.coded_width + 1) << 1;
READ_BITS(m_entryPointHdr.coded_height, 12);
m_entryPointHdr.coded_height = (m_entryPointHdr.coded_height + 1) << 1;
m_seqHdr.coded_width = m_entryPointHdr.coded_width;
m_seqHdr.coded_height = m_entryPointHdr.coded_height;
}
if (m_entryPointHdr.extended_mv)
READ(m_entryPointHdr.extended_dmv_flag);
READ(m_entryPointHdr.range_mapy_flag);
if (m_entryPointHdr.range_mapy_flag)
READ_BITS(m_entryPointHdr.range_mapy, 3);
READ(m_entryPointHdr.range_mapuv_flag);
if (m_entryPointHdr.range_mapy_flag)
READ_BITS(m_entryPointHdr.range_mapuv, 3);
return true;
}
bool Parser::parseSliceHeader(uint8_t* data, uint32_t size)
{
bool temp;
BitReader* br;
bool ret = true;
if (m_seqHdr.profile != PROFILE_ADVANCED)
return false;
BitReader bitReader(data, size);
br = &bitReader;
READ_BITS(m_sliceHdr.slice_addr, 9);
READ(temp);
if (temp)
ret = parseFrameHeaderAdvanced(&bitReader);
m_sliceHdr.macroblock_offset = bitReader.getPos();
return ret;
}
void Parser::mallocBitPlanes()
{
uint32_t size = m_mbHeight * m_mbWidth;
m_bitPlanes.acpred.resize(size);
m_bitPlanes.fieldtx.resize(size);
m_bitPlanes.overflags.resize(size);
m_bitPlanes.mvtypemb.resize(size);
m_bitPlanes.skipmb.resize(size);
m_bitPlanes.directmb.resize(size);
m_bitPlanes.forwardmb.resize(size);
}
bool Parser::decodeVLCTable(BitReader* br, uint16_t* out,
const VLCTable* table, uint32_t tableLen)
{
uint32_t i = 0;
uint16_t numberOfBits = 0;
uint16_t codeWord = 0;
while (i < tableLen) {
if (numberOfBits != table[i].codeLength) {
numberOfBits = table[i].codeLength;
PEEK(codeWord, numberOfBits);
}
if (codeWord == table[i].codeWord) {
*out = i;
SKIP(numberOfBits);
break;
}
i++;
}
return (i < tableLen) ? true : false;
}
/* 8.7.3.6 Row-skip mode*/
bool Parser::decodeRowskipMode(BitReader* br, uint8_t* data, uint32_t width, uint32_t height)
{
uint32_t i, j;
for (j = 0; j < height; j++) {
bool rowSkip;
READ(rowSkip);
if (rowSkip) {
for (i = 0; i < width; i++)
READ_BITS(data[i], 1);
}
else {
memset(data, 0, width);
}
data += m_mbWidth;
}
return true;
}
/* 8.7.3.7 Column-skip mode*/
bool Parser::decodeColskipMode(BitReader* br, uint8_t* data, uint32_t width, uint32_t height)
{
uint32_t i, j;
for (i = 0; i < width; i++) {
bool columnSkip;
READ(columnSkip);
if (columnSkip) {
for (j = 0; j < height; j++)
READ_BITS(data[j * m_mbWidth], 1);
}
else {
for (j = 0; j < height; j++)
data[j * m_mbWidth] = 0;
}
data++;
}
return true;
}
/* Table 80: Norm-2/Diff-2 Code Table */
bool Parser::decodeNorm2Mode(BitReader* br, uint8_t* data, uint32_t width, uint32_t height)
{
uint32_t i;
bool temp;
uint8_t* out = data;
if ((height * width) & 1) {
READ_BITS(*out, 1);
out++;
}
for (i = (height * width) & 1; i < height * width; i += 2) {
READ(temp);
if (temp == 0) {
*out++ = 0;
*out++ = 0;
}
else {
READ(temp);
if (temp) {
*out++ = 1;
*out++ = 1;
}
else {
READ(temp);
if (temp == 0) {
*out++ = 1;
*out++ = 0;
}
else {
*out++ = 0;
*out++ = 1;
}
}
}
}
return true;
}
bool Parser::decodeNorm6Mode(BitReader* br, uint8_t* data, uint32_t width, uint32_t height)
{
uint32_t i = 0, j = 0;
uint16_t temp;
uint8_t* out = data;
bool is2x3Tiled = (((width % 3) != 0) && ((height % 3) == 0));
if (is2x3Tiled) {
for (j = 0; j < height; j += 3) {
for (i = width & 1; i < width; i += 2) {
if (!decodeVLCTable(br, &temp, Norm6VLCTable, 64))
return false;
out[i] = temp & 1;
out[i + 1] = (temp & 2) >> 1;
out[i + width] = (temp & 4) >> 2;
out[i + width + 1] = (temp & 8) >> 3;
out[i + width * 2] = (temp & 16) >> 4;
out[i + width * 2 + 1] = (temp & 32) >> 5;
}
out += 3 * width;
}
if (width & 1)
decodeColskipMode(br, data, width & 1, height);
}
else {
out += (height & 1) * width;
for (j = height & 1; j < height; j += 2) {
for (i = width % 3; i < width; i += 3) {
if (!decodeVLCTable(br, &temp, Norm6VLCTable, 64))
return false;
out[i] = temp & 1;
out[i + 1] = (temp & 2) >> 1;
out[i + 2] = (temp & 4) >> 2;
out[i + width] = (temp & 8) >> 3;
out[i + width + 1] = (temp & 16) >> 4;
out[i + width + 2] = (temp & 32) >> 5;
}
out += 2 * width;
}
if (width % 3)
decodeColskipMode(br, data, width % 3, height);
if (height & 1)
decodeRowskipMode(br, data + (width % 3), width - (width % 3), height & 1);
}
return true;
}
/* 8.7.3.8 Diff: Inverse differential decoding */
void Parser::inverseDiff(uint8_t* data, uint32_t width, uint32_t height, uint32_t invert)
{
uint32_t i, j;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++) {
if ((i == 0) && (j == 0)) {
data[j * width + i] ^= invert;
}
else if (i == 0) {
data[j * width + i] ^= data[(j - 1) * width];
}
else if ((j > 0) && (data[(j - 1) * width + i] != data[j * width + i - 1])) {
data[j * width + i] ^= invert;
}
else {
data[j * width + i] ^= data[j * width + i - 1];
}
}
}
bool Parser::decodeBitPlane(BitReader* br, uint8_t* data, bool* isRaw)
{
uint32_t i, invert;
uint16_t mode;
*isRaw = false;
READ_BITS(invert, 1);
if (!decodeVLCTable(br, &mode, ImodeVLCTable, 7))
return false;
if (mode == IMODE_RAW) {
*isRaw = true;
return true;
}
else if (mode == IMODE_NORM2) {
decodeNorm2Mode(br, data, m_mbWidth, m_mbHeight);
}
else if (mode == IMODE_NORM6) {
decodeNorm6Mode(br, data, m_mbWidth, m_mbHeight);
}
else if (mode == IMODE_DIFF2) {
decodeNorm2Mode(br, data, m_mbWidth, m_mbHeight);
inverseDiff(data, m_mbWidth, m_mbHeight, invert);
}
else if (mode == IMODE_DIFF6) {
decodeNorm6Mode(br, data, m_mbWidth, m_mbHeight);
inverseDiff(data, m_mbWidth, m_mbHeight, invert);
}
else if (mode == IMODE_ROWSKIP) {
decodeRowskipMode(br, data, m_mbWidth, m_mbHeight);
}
else if (mode == IMODE_COLSKIP) {
decodeColskipMode(br, data, m_mbWidth, m_mbHeight);
}
/*8.7.1 INVERT*/
if ((mode != IMODE_DIFF2) && (mode != IMODE_DIFF6) && invert) {
for (i = 0; i < m_mbWidth * m_mbHeight; i++)
data[i] = !data[i];
}
return true;
}
/*Table 24: VOPDQUANT in picture header(Refer to 7.1.1.31)*/
/*7.1.1.31.6 Picture Quantizer Differential(PQDIFF)(3 bits)*/
bool Parser::parseVopdquant(BitReader* br, uint8_t dquant)
{
if (dquant == 2) {
m_frameHdr.dq_frame = 0;
READ_BITS(m_frameHdr.pq_diff, 3);
if (m_frameHdr.pq_diff != 7) {
m_frameHdr.alt_pic_quantizer = m_frameHdr.pquant + m_frameHdr.pq_diff + 1;
}
else {
READ_BITS(m_frameHdr.abs_pq, 5);
m_frameHdr.alt_pic_quantizer = m_frameHdr.abs_pq;
}
}
else {
READ(m_frameHdr.dq_frame);
if (m_frameHdr.dq_frame) {
READ_BITS(m_frameHdr.dq_profile, 2);
if (m_frameHdr.dq_profile == DQPROFILE_SINGLE_EDGE) {
READ_BITS(m_frameHdr.dq_sb_edge, 2);
}
else if (m_frameHdr.dq_profile == DQPROFILE_DOUBLE_EDGE) {
READ_BITS(m_frameHdr.dq_db_edge, 2);
}
else if (m_frameHdr.dq_profile == DQPROFILE_ALL_MACROBLOCKS) {
READ(m_frameHdr.dq_binary_level);
}
if (!((m_frameHdr.dq_profile == DQPROFILE_ALL_MACROBLOCKS)
&& (m_frameHdr.dq_binary_level == 0))) {
READ_BITS(m_frameHdr.pq_diff, 3);
if (m_frameHdr.pq_diff != 7) {
m_frameHdr.alt_pic_quantizer = m_frameHdr.pquant + m_frameHdr.pq_diff + 1;
}
else {
READ_BITS(m_frameHdr.abs_pq, 5);
m_frameHdr.alt_pic_quantizer = m_frameHdr.abs_pq;
}
}
}
}
return true;
}
int32_t Parser::getFirst01Bit(BitReader* br, bool val, uint32_t len)
{
uint32_t i = 0;
while (i < len) {
//TODO: check read beyond boundary here, it may need change so many functions
if (br->read(1) == val)
break;
i++;
}
return i;
}
uint8_t Parser::getMVMode(BitReader* br, uint8_t pQuant, bool isMvMode2)
{
int32_t temp = 0;
uint8_t MVMode = 0;
temp = isMvMode2 ? getFirst01Bit(br, 1, 3) : getFirst01Bit(br, 1, 4);
switch (temp) {
case 0:
MVMode = (pQuant <= 12) ? MVMODE_1_MV : MVMODE_1_MV_HALF_PEL_BILINEAR;
break;
case 1:
MVMode = (pQuant <= 12) ? MVMODE_MIXED_MV : MVMODE_1_MV;
break;
case 2:
MVMode = MVMODE_1_MV_HALF_PEL;
break;
case 3:
if (isMvMode2) {
MVMode = (pQuant <= 12) ? MVMODE_1_MV_HALF_PEL_BILINEAR : MVMODE_MIXED_MV;
}
else {
MVMode = MVMODE_INTENSITY_COMPENSATION;
}
break;
case 4:
if (!isMvMode2)
MVMode = (pQuant <= 12) ? MVMODE_1_MV_HALF_PEL_BILINEAR : MVMODE_MIXED_MV;
break;
default:
break;
}
return MVMode;
}
bool Parser::decodeBFraction(BitReader* br)
{
uint16_t bfraction;
if (!decodeVLCTable(br, &bfraction, BFractionVLCTable, N_ELEMENTS(BFractionVLCTable)))
return false;
m_frameHdr.bfraction = bfraction;
if (m_frameHdr.bfraction == 22) {
m_frameHdr.picture_type = FRAME_BI;
}
return true;
}
/*Table 16: Progressive I picture layer bitstream for Simple and Main Profile*/
/*Table 17: Progressive BI picture layer bitstream for Main Profile*/
/*Table 19: Progressive P picture layer bitstream for Simple and Main Profile*/
/*Table 21: Progressive B picture layer bitstream for Main Profile*/
bool Parser::parseFrameHeaderSimpleMain(BitReader* br)
{
bool temp;
m_frameHdr.interpfrm = 0;
if (m_seqHdr.finterpflag)
READ(m_frameHdr.interpfrm);
SKIP(2);
m_frameHdr.range_reduction_frame = 0;
if (m_seqHdr.rangered)
READ(m_frameHdr.range_reduction_frame);
READ(temp);
if (m_seqHdr.max_b_frames == 0) {
/* Table 33 Simple/Main Profile Picture Type VLC if MAXBFRAMES == 0 */
if (!temp)
m_frameHdr.picture_type = FRAME_I;
else
m_frameHdr.picture_type = FRAME_P;
}
else {
/* Table 34 Main Profile Picture Type VLC if MAXBFRAMES > 0 */
if (!temp) {
bool ptype;
READ(ptype);
if (ptype)
m_frameHdr.picture_type = FRAME_I;
else
m_frameHdr.picture_type = FRAME_B;
}
else {
m_frameHdr.picture_type = FRAME_P;
}
}
if (m_frameHdr.picture_type == FRAME_B) {
if (!decodeBFraction(br))
return false;
}
if (m_frameHdr.picture_type == FRAME_I
|| m_frameHdr.picture_type == FRAME_BI)
SKIP(7); /* skip BF*/
READ_BITS(m_frameHdr.pqindex, 5);
if (m_frameHdr.pqindex <= 8)
READ(m_frameHdr.halfqp);
if (m_seqHdr.quantizer == 0) {
m_frameHdr.pquant = QuantizerTranslationTable[m_frameHdr.pqindex];
m_frameHdr.pquantizer = (m_frameHdr.pqindex <= 8) ? 1 : 0;
}
else {
m_frameHdr.pquant = m_frameHdr.pqindex;
if (m_seqHdr.quantizer == 1)
READ(m_frameHdr.pquantizer);
else if (m_seqHdr.quantizer == 2)
m_frameHdr.pquantizer = 0;
else if (m_seqHdr.quantizer == 3)
m_frameHdr.pquantizer = 1;
else
assert(0);
}
if (m_seqHdr.extended_mv)
m_frameHdr.extended_mv_range = getFirst01Bit(br, 0, 3);
if (m_seqHdr.multires
&& ((m_frameHdr.picture_type == FRAME_I)
|| (m_frameHdr.picture_type == FRAME_P))) {
READ_BITS(m_frameHdr.picture_resolution_index, 2);
}
if ((m_frameHdr.picture_type == FRAME_I)
|| (m_frameHdr.picture_type == FRAME_BI)) {
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
m_frameHdr.transacfrm2 = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
}
else if (m_frameHdr.picture_type == FRAME_P) {
m_frameHdr.mv_mode = getMVMode(br, m_frameHdr.pquant, false);
if (m_frameHdr.mv_mode == MVMODE_INTENSITY_COMPENSATION) {
m_frameHdr.mv_mode2 = getMVMode(br, m_frameHdr.pquant, true);
READ_BITS(m_frameHdr.lumscale, 6);
READ_BITS(m_frameHdr.lumshift, 6);
}
if (m_frameHdr.mv_mode == MVMODE_MIXED_MV
|| (m_frameHdr.mv_mode == MVMODE_INTENSITY_COMPENSATION
&& m_frameHdr.mv_mode2 == MVMODE_MIXED_MV)) {
if (!decodeBitPlane(br, &m_bitPlanes.mvtypemb[0], &m_frameHdr.mv_type_mb))
return false;
}
if (!decodeBitPlane(br, &m_bitPlanes.skipmb[0], &m_frameHdr.skip_mb))
return false;
READ_BITS(m_frameHdr.mv_table, 2);
READ_BITS(m_frameHdr.cbp_table, 2);
if (m_seqHdr.dquant)
parseVopdquant(br, m_seqHdr.dquant);
if (m_seqHdr.variable_sized_transform_flag) {
READ(m_frameHdr.mb_level_transform_type_flag);
if (m_frameHdr.mb_level_transform_type_flag)
READ_BITS(m_frameHdr.frame_level_transform_type, 2);
}
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
}
else if (m_frameHdr.picture_type == FRAME_B) {
READ_BITS(m_frameHdr.mv_mode, 1);
m_frameHdr.mv_mode = !(m_frameHdr.mv_mode);
if (!decodeBitPlane(br, &m_bitPlanes.directmb[0], &m_frameHdr.direct_mb))
return false;
if (!decodeBitPlane(br, &m_bitPlanes.skipmb[0], &m_frameHdr.skip_mb))
return false;
READ_BITS(m_frameHdr.mv_table, 2);
READ_BITS(m_frameHdr.cbp_table, 2);
if (m_seqHdr.dquant)
parseVopdquant(br, m_seqHdr.dquant);
if (m_seqHdr.variable_sized_transform_flag) {
READ(m_frameHdr.mb_level_transform_type_flag);
if (m_frameHdr.mb_level_transform_type_flag)
READ_BITS(m_frameHdr.frame_level_transform_type, 2);
}
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
}
return true;
}
/* 9.1.1.43 P Reference Distance*/
/* Table 106: REFDIST VLC Table*/
bool Parser::getRefDist(BitReader* br, uint8_t& refDist)
{
uint32_t vlcSize;
PEEK(vlcSize, 2);
if (vlcSize != 3) {
READ_BITS(refDist, 2);
}
else {
//TODO: check read beyond boundary
refDist = getFirst01Bit(br, 0, 16) + 1;
}
return true;
}
/*Table 18: Progressive I and BI picture layer bitstream for Advanced Profile*/
/*Table 20: Progressive P picture layer bitstream for Advanced Profile*/
/*Table 22: Progressive B picture layer bitstream for Advanced Profile*/
/*Table 83: Interlaced Frame P picture layer bitstream for Advanced Profile*/
/*Table 84: Interlaced Frame B picture layer bitstream for Advanced Profile*/
/*Table 85: Picture Layer bitstream for Field 1 of Interlace Field Picture for Advanced Profile*/
bool Parser::parseFrameHeaderAdvanced(BitReader* br)
{
uint32_t temp;
if (m_seqHdr.interlace) {
m_frameHdr.fcm = getFirst01Bit(br, 0, 2);
}
else {
m_frameHdr.fcm = PROGRESSIVE;
}
if (m_frameHdr.fcm == FIELD_INTERLACE) {
READ_BITS(temp, 3);
/* 9.1.1.42 Field Picture Type(FPTYPE) (3 bits) */
m_frameHdr.picture_type = FrameTypeTable[0][temp];
}
else {
/* Table 35 Advanced Profile Picture Type VLC */
temp = getFirst01Bit(br, 0, 4);
m_frameHdr.picture_type = FrameTypeTable[1][temp];
}
/* skip tfcntr */
if (m_seqHdr.tfcntrflag)
SKIP(8);
if (m_seqHdr.pulldown) {
if (!(m_seqHdr.interlace) || m_seqHdr.psf) {
READ_BITS(m_frameHdr.rptfrm, 2);
}
else {
READ(m_frameHdr.tff);
READ(m_frameHdr.rff);
}
}
else {
m_frameHdr.tff = 1;
}
if (m_frameHdr.picture_type == FRAME_SKIPPED)
return true;
READ(m_frameHdr.rounding_control);
if (m_seqHdr.interlace) {
READ(m_frameHdr.uvsamp);
if ((m_frameHdr.fcm == FIELD_INTERLACE)
&& m_entryPointHdr.reference_distance_flag
&& (m_frameHdr.picture_type != FRAME_B)
&& (m_frameHdr.picture_type != FRAME_BI)) {
if (!getRefDist(br, m_frameHdr.refdist))
return false;
}
}
if (m_seqHdr.finterpflag)
READ(m_frameHdr.interpfrm);
if ((m_frameHdr.fcm != FIELD_INTERLACE
&& m_frameHdr.picture_type == FRAME_B)
|| (m_frameHdr.fcm == FIELD_INTERLACE
&& ((m_frameHdr.picture_type == FRAME_B)
|| (m_frameHdr.picture_type == FRAME_BI)))) {
if (!decodeBFraction(br))
return false;
}
READ_BITS(m_frameHdr.pqindex, 5);
if (m_frameHdr.pqindex <= 8)
READ(m_frameHdr.halfqp);
if (m_entryPointHdr.quantizer == 0) {
m_frameHdr.pquant = QuantizerTranslationTable[m_frameHdr.pqindex];
m_frameHdr.pquantizer = (m_frameHdr.pqindex <= 8);
}
else {
m_frameHdr.pquant = m_frameHdr.pqindex;
if (m_entryPointHdr.quantizer == 1)
READ(m_frameHdr.pquantizer);
else if (m_entryPointHdr.quantizer == 2)
m_frameHdr.pquantizer = 0;
else if (m_entryPointHdr.quantizer == 3)
m_frameHdr.pquantizer = 1;
else
assert(0);
}
if (m_seqHdr.postprocflag)
READ_BITS(m_frameHdr.post_processing, 2);
if ((m_frameHdr.picture_type == FRAME_I)
|| (m_frameHdr.picture_type == FRAME_BI)) {
if (m_frameHdr.fcm == FRAME_INTERLACE) {
if (!decodeBitPlane(br, &m_bitPlanes.fieldtx[0], &m_frameHdr.fieldtx))
return false;
}
if (!decodeBitPlane(br, &m_bitPlanes.acpred[0], &m_frameHdr.ac_pred))
return false;
if ((m_entryPointHdr.overlap) && m_frameHdr.pquant <= 8) {
m_frameHdr.condover = getFirst01Bit(br, 0, 2);
if (m_frameHdr.condover == 2) {
if (!decodeBitPlane(br, &m_bitPlanes.overflags[0], &m_frameHdr.overflags))
return false;
}
}
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
m_frameHdr.transacfrm2 = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
if (m_entryPointHdr.dquant)
parseVopdquant(br, m_entryPointHdr.dquant);
}
else if (m_frameHdr.picture_type == FRAME_P) {
if (m_frameHdr.fcm == FIELD_INTERLACE) {
READ(m_frameHdr.numref);
if (m_frameHdr.numref)
READ(m_frameHdr.reffield);
}
if (m_entryPointHdr.extended_mv)
m_frameHdr.extended_mv_range = getFirst01Bit(br, 0, 3);
if (m_frameHdr.fcm != PROGRESSIVE) {
if (m_entryPointHdr.extended_dmv_flag)
m_frameHdr.dmvrange = getFirst01Bit(br, 0, 3);
}
if (m_frameHdr.fcm == FRAME_INTERLACE) {
READ(m_frameHdr.mvswitch4);
READ(m_frameHdr.intcomp);
if (m_frameHdr.intcomp) {
READ_BITS(m_frameHdr.lumscale, 6);
READ_BITS(m_frameHdr.lumshift, 6);
}
}
else {
m_frameHdr.mv_mode = getMVMode(br, m_frameHdr.pquant, false);
if (m_frameHdr.mv_mode == MVMODE_INTENSITY_COMPENSATION) {
m_frameHdr.mv_mode2 = getMVMode(br, m_frameHdr.pquant, true);
if (m_frameHdr.fcm == FIELD_INTERLACE) {
temp = getFirst01Bit(br, 1, 2);
m_frameHdr.intcompfield = temp ? (3 - temp) : temp;
}
READ_BITS(m_frameHdr.lumscale, 6);
READ_BITS(m_frameHdr.lumshift, 6);
if ((m_frameHdr.fcm == FIELD_INTERLACE)
&& m_frameHdr.intcompfield) {
READ_BITS(m_frameHdr.lumscale2, 6);
READ_BITS(m_frameHdr.lumshift2, 6);
}
}
if (m_frameHdr.fcm == PROGRESSIVE) {
if (m_frameHdr.mv_mode == MVMODE_MIXED_MV
|| (m_frameHdr.mv_mode == MVMODE_INTENSITY_COMPENSATION
&& m_frameHdr.mv_mode2 == MVMODE_MIXED_MV)) {
if (!decodeBitPlane(br, &m_bitPlanes.mvtypemb[0], &m_frameHdr.mv_type_mb))
return false;
}
}
}
if (m_frameHdr.fcm != FIELD_INTERLACE) {
if (!decodeBitPlane(br, &m_bitPlanes.skipmb[0], &m_frameHdr.skip_mb))
return false;
}
if (m_frameHdr.fcm != PROGRESSIVE) {
READ_BITS(m_frameHdr.mbmodetab, 2);
READ_BITS(m_frameHdr.imvtab, 2);
READ_BITS(m_frameHdr.icbptab, 3);
if (m_frameHdr.fcm != FIELD_INTERLACE) {
READ_BITS(m_frameHdr.mvbptab2, 2);
if (m_frameHdr.mvswitch4)
READ_BITS(m_frameHdr.mvbptab4, 2);
}
else if (m_frameHdr.mv_mode == MVMODE_MIXED_MV) {
READ_BITS(m_frameHdr.mvbptab4, 2);
}
}
else {
READ_BITS(m_frameHdr.mv_table, 2);
READ_BITS(m_frameHdr.cbp_table, 2);
}
if (m_entryPointHdr.dquant)
parseVopdquant(br, m_entryPointHdr.dquant);
if (m_entryPointHdr.variable_sized_transform_flag) {
READ(m_frameHdr.mb_level_transform_type_flag);
if (m_frameHdr.mb_level_transform_type_flag)
READ_BITS(m_frameHdr.frame_level_transform_type, 2);
}
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
}
else if (m_frameHdr.picture_type == FRAME_B) {
if (m_entryPointHdr.extended_mv)
m_frameHdr.extended_mv_range = getFirst01Bit(br, 0, 3);
if (m_frameHdr.fcm != PROGRESSIVE) {
if (m_entryPointHdr.extended_dmv_flag)
m_frameHdr.dmvrange = getFirst01Bit(br, 0, 3);
}
if (m_frameHdr.fcm == FRAME_INTERLACE) {
READ(m_frameHdr.intcomp);
}
else {
READ_BITS(m_frameHdr.mv_mode, 1);
m_frameHdr.mv_mode = !(m_frameHdr.mv_mode);
}
if (m_frameHdr.fcm == FIELD_INTERLACE) {
if (!decodeBitPlane(br, &m_bitPlanes.forwardmb[0], &m_frameHdr.forwardmb))
return false;
}
else {
if (!decodeBitPlane(br, &m_bitPlanes.directmb[0], &m_frameHdr.direct_mb))
return false;
if (!decodeBitPlane(br, &m_bitPlanes.skipmb[0], &m_frameHdr.skip_mb))
return false;
}
if (m_frameHdr.fcm != PROGRESSIVE) {
READ_BITS(m_frameHdr.mbmodetab, 2);
READ_BITS(m_frameHdr.imvtab, 2);
READ_BITS(m_frameHdr.icbptab, 3);
if (m_frameHdr.fcm == FRAME_INTERLACE)
READ_BITS(m_frameHdr.mvbptab2, 2);
if ((m_frameHdr.fcm == FRAME_INTERLACE)
|| ((m_frameHdr.fcm == FIELD_INTERLACE)
&& (m_frameHdr.mv_mode == MVMODE_MIXED_MV)))
READ_BITS(m_frameHdr.mvbptab4, 2);
}
else {
READ_BITS(m_frameHdr.mv_table, 2);
READ_BITS(m_frameHdr.cbp_table, 2);
}
if (m_entryPointHdr.dquant)
parseVopdquant(br, m_entryPointHdr.dquant);
if (m_entryPointHdr.variable_sized_transform_flag) {
READ(m_frameHdr.mb_level_transform_type_flag);
if (m_frameHdr.mb_level_transform_type_flag)
READ_BITS(m_frameHdr.frame_level_transform_type, 2);
}
m_frameHdr.transacfrm = getFirst01Bit(br, 0, 2);
READ(m_frameHdr.intra_transform_dc_table);
}
return true;
}
}
}