Merge pull request #524 from jcdr428/Simplify_VC1_Class
Simplify VC1 classes
This commit is contained in:
commit
ce632ae77d
@ -36,7 +36,7 @@ static inline int decode012(BitStreamReader& bitReader)
|
||||
void VC1Unit::updateBits(int bitOffset, int bitLen, int value)
|
||||
{
|
||||
uint8_t* ptr = (uint8_t*)bitReader.getBuffer() + bitOffset / 8;
|
||||
BitStreamWriter bitWriter;
|
||||
BitStreamWriter bitWriter{};
|
||||
int byteOffset = bitOffset % 8;
|
||||
bitWriter.setBuffer(ptr, ptr + (bitLen / 8 + 5));
|
||||
|
||||
@ -66,16 +66,16 @@ string VC1SequenceHeader::getStreamDescr()
|
||||
rez << "Profile: ";
|
||||
switch (profile)
|
||||
{
|
||||
case PROFILE_SIMPLE:
|
||||
case Profile::PROFILE_SIMPLE:
|
||||
rez << "Simple";
|
||||
break;
|
||||
case PROFILE_MAIN:
|
||||
case Profile::PROFILE_MAIN:
|
||||
rez << "Main";
|
||||
break;
|
||||
case PROFILE_COMPLEX:
|
||||
case Profile::PROFILE_COMPLEX:
|
||||
rez << "Complex";
|
||||
break;
|
||||
case PROFILE_ADVANCED:
|
||||
case Profile::PROFILE_ADVANCED:
|
||||
rez << "Advanced@" << level;
|
||||
break;
|
||||
default:
|
||||
@ -107,11 +107,12 @@ void VC1SequenceHeader::setFPS(double value)
|
||||
{
|
||||
// if (value < 25.0 && pulldown)
|
||||
// value *= 1.25;
|
||||
int nr, dr;
|
||||
|
||||
if (m_fpsFieldBitVal > 0)
|
||||
{
|
||||
int time_scale = (uint32_t)(value + 0.5) * 1000;
|
||||
int num_units_in_tick = time_scale / value + 0.5;
|
||||
int nr, dr;
|
||||
int time_scale = (int)(value + 0.5) * 1000;
|
||||
int num_units_in_tick = (int)(time_scale / value + 0.5);
|
||||
if ((time_scale == 24000 || time_scale == 25000 || time_scale == 30000 || time_scale == 50000 ||
|
||||
time_scale == 60000) &&
|
||||
(num_units_in_tick == 1000 || num_units_in_tick == 1001))
|
||||
@ -122,25 +123,33 @@ void VC1SequenceHeader::setFPS(double value)
|
||||
else
|
||||
THROW(ERR_VC1_ERR_FPS,
|
||||
"Can't overwrite stream fps. Non standard fps values not supported for VC-1 streams");
|
||||
if (time_scale == 24000)
|
||||
|
||||
switch (time_scale)
|
||||
{
|
||||
case 24000:
|
||||
nr = 1;
|
||||
else if (time_scale == 25000)
|
||||
break;
|
||||
case 25000:
|
||||
nr = 2;
|
||||
else if (time_scale == 30000)
|
||||
break;
|
||||
case 30000:
|
||||
nr = 3;
|
||||
else if (time_scale == 50000)
|
||||
break;
|
||||
case 50000:
|
||||
nr = 4;
|
||||
else // if (time_scale == 60000)
|
||||
break;
|
||||
case 60000:
|
||||
nr = 5;
|
||||
if (num_units_in_tick == 1000)
|
||||
dr = 1;
|
||||
else
|
||||
dr = 2;
|
||||
break;
|
||||
default:
|
||||
THROW(ERR_VC1_ERR_FPS,
|
||||
"Can't overwrite stream fps. Non standard fps values not supported for VC-1 streams");
|
||||
}
|
||||
dr = (num_units_in_tick == 1000) ? 1 : 2;
|
||||
|
||||
updateBits(m_fpsFieldBitVal, 8, nr);
|
||||
updateBits(m_fpsFieldBitVal + 8, 4, dr);
|
||||
}
|
||||
else
|
||||
THROW(ERR_VC1_ERR_FPS, "Can't overwrite stream fps. Non standard fps values not supported for VC-1 streams");
|
||||
}
|
||||
|
||||
int VC1SequenceHeader::decode_sequence_header()
|
||||
@ -148,15 +157,15 @@ int VC1SequenceHeader::decode_sequence_header()
|
||||
try
|
||||
{
|
||||
bitReader.setBuffer(m_nalBuffer, m_nalBuffer + m_nalBufferLen); // skip 00 00 01 xx marker
|
||||
profile = bitReader.getBits(2);
|
||||
if (profile == PROFILE_COMPLEX)
|
||||
profile = (Profile)bitReader.getBits(2);
|
||||
if (profile == Profile::PROFILE_COMPLEX)
|
||||
LTRACE(LT_WARN, 0, "WMV3 Complex Profile is not fully supported");
|
||||
|
||||
if (profile == PROFILE_ADVANCED)
|
||||
else if (profile == Profile::PROFILE_ADVANCED)
|
||||
return decode_sequence_header_adv();
|
||||
else
|
||||
{
|
||||
res_sm = bitReader.getBits(2); // reserved
|
||||
int res_sm = bitReader.getBits(2); // reserved
|
||||
if (res_sm)
|
||||
{
|
||||
LTRACE(LT_ERROR, 0, "Reserved RES_SM=" << res_sm << " is forbidden");
|
||||
@ -164,48 +173,42 @@ int VC1SequenceHeader::decode_sequence_header()
|
||||
}
|
||||
}
|
||||
|
||||
frmrtq_postproc = bitReader.getBits(3); // common
|
||||
bitrtq_postproc = bitReader.getBits(5); // common
|
||||
loop_filter = bitReader.getBit(); // common
|
||||
if (loop_filter == 1 && profile == PROFILE_SIMPLE)
|
||||
bitReader.skipBits(8); // frmrtq_postproc, bitrtq_postproc
|
||||
if (bitReader.getBit() && profile == Profile::PROFILE_SIMPLE) // loop_filter
|
||||
LTRACE(LT_WARN, 0, "LOOPFILTER shell not be enabled in simple profile");
|
||||
int res_x8 = bitReader.getBit(); // reserved
|
||||
if (res_x8)
|
||||
if (bitReader.getBit()) // reserved res_x8
|
||||
LTRACE(LT_WARN, 0, "1 for reserved RES_X8 is forbidden");
|
||||
multires = bitReader.getBit();
|
||||
int res_fasttx = bitReader.getBit();
|
||||
bitReader.skipBit(); // multires
|
||||
int res_fasttx = bitReader.getBit(); // reserved
|
||||
if (!res_fasttx)
|
||||
LTRACE(LT_WARN, 0, "0 for reserved RES_FASTTX is forbidden");
|
||||
fastuvmc = bitReader.getBit();
|
||||
if (!profile && !fastuvmc)
|
||||
if (profile == Profile::PROFILE_SIMPLE && !bitReader.getBit()) // fastuvmc
|
||||
{
|
||||
LTRACE(LT_ERROR, 0, "FASTUVMC unavailable in Simple Profile");
|
||||
return NALUnit::UNSUPPORTED_PARAM;
|
||||
}
|
||||
extended_mv = bitReader.getBit();
|
||||
if (!profile && extended_mv)
|
||||
if (profile == Profile::PROFILE_SIMPLE && bitReader.getBit()) // extended_mv
|
||||
{
|
||||
LTRACE(LT_ERROR, 0, "Extended MVs unavailable in Simple Profile");
|
||||
return NALUnit::UNSUPPORTED_PARAM;
|
||||
}
|
||||
dquant = bitReader.getBits(2);
|
||||
vstransform = bitReader.getBit();
|
||||
int res_transtab = bitReader.getBit();
|
||||
if (res_transtab)
|
||||
bitReader.skipBits(3); // dquant, vstransform
|
||||
|
||||
if (bitReader.getBit()) // res_transtab
|
||||
{
|
||||
LTRACE(LT_ERROR, 0, "1 for reserved RES_TRANSTAB is forbidden\n");
|
||||
return NALUnit::UNSUPPORTED_PARAM;
|
||||
}
|
||||
overlap = bitReader.getBit();
|
||||
resync_marker = bitReader.getBit();
|
||||
bitReader.skipBits(2); // overlap, resync_marker
|
||||
|
||||
rangered = bitReader.getBit();
|
||||
if (rangered && profile == PROFILE_SIMPLE)
|
||||
if (rangered && profile == Profile::PROFILE_SIMPLE)
|
||||
LTRACE(LT_WARN, 0, "RANGERED should be set to 0 in simple profile");
|
||||
max_b_frames = bitReader.getBits(3);
|
||||
quantizer_mode = bitReader.getBits(2);
|
||||
bitReader.skipBits(2); // quantizer_mode
|
||||
finterpflag = bitReader.getBit();
|
||||
int res_rtm_flag = bitReader.getBit();
|
||||
if (res_rtm_flag)
|
||||
|
||||
if (!bitReader.getBit()) // res_rtm_flag
|
||||
LTRACE(LT_WARN, 0, "Old WMV3 version detected.");
|
||||
// TODO: figure out what they mean (always 0x402F)
|
||||
if (!res_fasttx)
|
||||
@ -223,10 +226,7 @@ int VC1SequenceHeader::decode_sequence_header_adv()
|
||||
level = bitReader.getBits(3);
|
||||
if (level >= 5)
|
||||
LTRACE(LT_WARN, 0, "Reserved LEVEL " << level);
|
||||
chromaformat = bitReader.getBits(2);
|
||||
frmrtq_postproc = bitReader.getBits(3); // common
|
||||
bitrtq_postproc = bitReader.getBits(5); // common
|
||||
postprocflag = bitReader.getBit(); // common
|
||||
bitReader.skipBits(11); // chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag
|
||||
coded_width = (bitReader.getBits(12) + 1) << 1;
|
||||
coded_height = (bitReader.getBits(12) + 1) << 1;
|
||||
pulldown = bitReader.getBit();
|
||||
@ -284,49 +284,36 @@ if(psf) { //PsF, 6.1.13
|
||||
}
|
||||
|
||||
if (bitReader.getBit())
|
||||
{
|
||||
color_prim = bitReader.getBits(8);
|
||||
transfer_char = bitReader.getBits(8);
|
||||
matrix_coef = bitReader.getBits(8);
|
||||
}
|
||||
bitReader.skipBits(24); // color_prim, transfer_char, matrix_coef
|
||||
}
|
||||
|
||||
hrd_param_flag = bitReader.getBit();
|
||||
if (hrd_param_flag)
|
||||
{
|
||||
hrd_num_leaky_buckets = bitReader.getBits(5);
|
||||
bitReader.skipBits(4); // bitrate exponent
|
||||
bitReader.skipBits(4); // buffer size exponent
|
||||
for (int i = 0; i < hrd_num_leaky_buckets; i++)
|
||||
{
|
||||
bitReader.skipBits(16); // hrd_rate[n]
|
||||
bitReader.skipBits(16); // hrd_buffer[n]
|
||||
}
|
||||
bitReader.skipBits(8); // bitrate exponent, buffer size exponent
|
||||
for (int i = 0; i < hrd_num_leaky_buckets; i++) bitReader.skipBits(32); // hrd_rate[n], hrd_buffer[n]
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VC1SequenceHeader::decode_entry_point()
|
||||
{
|
||||
int i, blink, clentry, refdist;
|
||||
try
|
||||
{
|
||||
bitReader.setBuffer(m_nalBuffer, m_nalBuffer + m_nalBufferLen); // skip 00 00 01 xx marker
|
||||
blink = bitReader.getBit(); // broken link
|
||||
clentry = bitReader.getBit(); // closed entry
|
||||
panscanflag = bitReader.getBit();
|
||||
refdist = bitReader.getBit(); // refdist flag
|
||||
loop_filter = bitReader.getBit();
|
||||
fastuvmc = bitReader.getBit();
|
||||
extended_mv = bitReader.getBit();
|
||||
dquant = bitReader.getBits(2);
|
||||
vstransform = bitReader.getBit();
|
||||
overlap = bitReader.getBit();
|
||||
quantizer_mode = bitReader.getBits(2);
|
||||
bitReader.skipBit(); // blink = broken link
|
||||
bitReader.skipBit(); // clentry = closed entry
|
||||
bitReader.skipBit(); // panscanflag
|
||||
bitReader.skipBit(); // refdist flag
|
||||
bitReader.skipBit(); // loop_filter
|
||||
bitReader.skipBit(); // fastuvmc
|
||||
int extended_mv = bitReader.getBit();
|
||||
bitReader.skipBits(6); // dquant, vstransform, overlap, quantizer_mode
|
||||
|
||||
if (hrd_param_flag)
|
||||
{
|
||||
for (i = 0; i < hrd_num_leaky_buckets; i++) bitReader.skipBits(8); // hrd_full[n]
|
||||
for (int i = 0; i < hrd_num_leaky_buckets; i++) bitReader.skipBits(8); // hrd_full[n]
|
||||
}
|
||||
|
||||
if (bitReader.getBit())
|
||||
@ -335,7 +322,7 @@ int VC1SequenceHeader::decode_entry_point()
|
||||
coded_height = (bitReader.getBits(12) + 1) << 1;
|
||||
}
|
||||
if (extended_mv)
|
||||
extended_dmv = bitReader.getBit();
|
||||
bitReader.skipBit(); // extended_dmv
|
||||
if (bitReader.getBit())
|
||||
{
|
||||
// av_log(avctx, AV_LOG_ERROR, "Luma scaling is not supported, expect wrong picture\n");
|
||||
@ -361,7 +348,7 @@ int VC1Frame::decode_frame_direct(const VC1SequenceHeader& sequenceHdr, uint8_t*
|
||||
try
|
||||
{
|
||||
bitReader.setBuffer(buffer, end); // skip 00 00 01 xx marker
|
||||
if (sequenceHdr.profile < PROFILE_ADVANCED)
|
||||
if (sequenceHdr.profile < Profile::PROFILE_ADVANCED)
|
||||
return vc1_parse_frame_header(sequenceHdr);
|
||||
else
|
||||
return vc1_parse_frame_header_adv(sequenceHdr);
|
||||
@ -374,13 +361,11 @@ int VC1Frame::decode_frame_direct(const VC1SequenceHeader& sequenceHdr, uint8_t*
|
||||
|
||||
int VC1Frame::vc1_parse_frame_header(const VC1SequenceHeader& sequenceHdr)
|
||||
{
|
||||
interpfrm = -1;
|
||||
if (sequenceHdr.finterpflag)
|
||||
interpfrm = bitReader.getBit();
|
||||
framecnt = bitReader.getBits(2); // framecnt unused
|
||||
rangeredfrm = 0;
|
||||
bitReader.skipBit(); // interpfrm
|
||||
bitReader.skipBits(2); // framecnt
|
||||
if (sequenceHdr.rangered)
|
||||
rangeredfrm = bitReader.getBit();
|
||||
bitReader.skipBit(); // rangeredfrm
|
||||
pict_type = (VC1PictType)bitReader.getBit();
|
||||
if (sequenceHdr.max_b_frames > 0)
|
||||
{
|
||||
@ -401,42 +386,8 @@ int VC1Frame::vc1_parse_frame_header(const VC1SequenceHeader& sequenceHdr)
|
||||
|
||||
int VC1Frame::vc1_parse_frame_header_adv(const VC1SequenceHeader& sequenceHdr)
|
||||
{
|
||||
fcm = 0;
|
||||
if (sequenceHdr.interlace)
|
||||
fcm = decode012(bitReader);
|
||||
fcm = sequenceHdr.interlace ? decode012(bitReader) : 0;
|
||||
|
||||
/*
|
||||
if (fcm == 2) // is coded field
|
||||
{
|
||||
int tmpType = bitReader.getBits(3);
|
||||
switch(tmpType) {
|
||||
case 0:
|
||||
pict_type = I_TYPE;
|
||||
break;
|
||||
case 1:
|
||||
pict_type = isFrame ? I_TYPE : P_TYPE;
|
||||
break;
|
||||
case 2:
|
||||
pict_type = isFrame ? P_TYPE : I_TYPE;
|
||||
break;
|
||||
case 3:
|
||||
pict_type = P_TYPE;
|
||||
break;
|
||||
case 4:
|
||||
pict_type = B_TYPE;
|
||||
break;
|
||||
case 5:
|
||||
pict_type = isFrame ? B_TYPE : BI_TYPE;
|
||||
break;
|
||||
case 6:
|
||||
pict_type = isFrame ? BI_TYPE : B_TYPE;
|
||||
break;
|
||||
case 7:
|
||||
pict_type = isFrame ? BI_TYPE : B_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (fcm == 2) // is coded field
|
||||
{
|
||||
switch (bitReader.getBits(3))
|
||||
@ -482,7 +433,7 @@ int VC1Frame::vc1_parse_frame_header_adv(const VC1SequenceHeader& sequenceHdr)
|
||||
}
|
||||
|
||||
if (sequenceHdr.tfcntrflag)
|
||||
int TFCNTR = bitReader.getBits(8);
|
||||
bitReader.skipBits(8); // TFCNTR
|
||||
if (sequenceHdr.pulldown)
|
||||
{
|
||||
rptfrmBitPos = bitReader.getBitsCount();
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "memory.h"
|
||||
#include "vod_common.h"
|
||||
|
||||
enum VC1Code
|
||||
enum class VC1Code
|
||||
{
|
||||
VC1_CODE_ENDOFSEQ = 0x0A,
|
||||
VC1_CODE_SLICE,
|
||||
@ -25,16 +25,13 @@ enum VC1Code
|
||||
VC1_USER_CODE_SEQHDR
|
||||
};
|
||||
|
||||
/** Available Profiles */
|
||||
//@{
|
||||
enum Profile
|
||||
enum class Profile
|
||||
{
|
||||
PROFILE_SIMPLE,
|
||||
PROFILE_MAIN,
|
||||
PROFILE_COMPLEX, ///< TODO: WMV9 specific
|
||||
PROFILE_ADVANCED
|
||||
};
|
||||
//@}
|
||||
|
||||
const int ff_vc1_fps_nr[7] = {24, 25, 30, 50, 60, 48, 72};
|
||||
const int ff_vc1_fps_dr[2] = {1000, 1001};
|
||||
@ -87,18 +84,18 @@ class VC1Unit
|
||||
}
|
||||
return end;
|
||||
}
|
||||
inline int vc1_unescape_buffer(uint8_t* src, int size)
|
||||
inline size_t vc1_unescape_buffer(uint8_t* src, size_t size)
|
||||
{
|
||||
delete[] m_nalBuffer;
|
||||
m_nalBuffer = new uint8_t[size];
|
||||
int dsize = 0, i;
|
||||
size_t dsize = 0;
|
||||
if (size < 4)
|
||||
{
|
||||
std::copy(src, src + size, m_nalBuffer);
|
||||
m_nalBufferLen = size;
|
||||
return size;
|
||||
}
|
||||
for (i = 0; i < size; i++, src++)
|
||||
for (size_t i = 0; i < size; i++, src++)
|
||||
{
|
||||
if (src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size - 1 && src[1] < 4)
|
||||
{
|
||||
@ -148,55 +145,55 @@ class VC1Unit
|
||||
void updateBits(int bitOffset, int bitLen, int value);
|
||||
BitStreamReader bitReader;
|
||||
uint8_t* m_nalBuffer;
|
||||
uint32_t m_nalBufferLen;
|
||||
size_t m_nalBufferLen;
|
||||
};
|
||||
|
||||
class VC1SequenceHeader : public VC1Unit
|
||||
{
|
||||
public:
|
||||
VC1SequenceHeader()
|
||||
: VC1Unit(), interlace(0), time_base_num(0), time_base_den(0), m_fpsFieldBitVal(0), sample_aspect_ratio(1, 1)
|
||||
: VC1Unit(),
|
||||
profile(Profile::PROFILE_SIMPLE),
|
||||
level(0),
|
||||
interlace(0),
|
||||
time_base_num(0),
|
||||
time_base_den(0),
|
||||
m_fpsFieldBitVal(0),
|
||||
sample_aspect_ratio(1, 1),
|
||||
coded_height(0),
|
||||
coded_width(0),
|
||||
display_height(0),
|
||||
display_width(0),
|
||||
finterpflag(false),
|
||||
hrd_param_flag(false),
|
||||
hrd_num_leaky_buckets(0),
|
||||
psf(0),
|
||||
pulldown(0),
|
||||
rangered(0),
|
||||
max_b_frames(0),
|
||||
tfcntrflag(false)
|
||||
{
|
||||
}
|
||||
int profile;
|
||||
int res_sm;
|
||||
int frmrtq_postproc;
|
||||
int bitrtq_postproc;
|
||||
int loop_filter;
|
||||
int multires;
|
||||
int fastuvmc;
|
||||
int extended_mv;
|
||||
int dquant;
|
||||
int vstransform;
|
||||
int overlap;
|
||||
int resync_marker;
|
||||
Profile profile;
|
||||
int rangered;
|
||||
int max_b_frames;
|
||||
int quantizer_mode;
|
||||
int finterpflag; ///< INTERPFRM present
|
||||
int level;
|
||||
int chromaformat; ///< 2bits, 2=4:2:0, only defined
|
||||
int coded_width;
|
||||
int coded_height;
|
||||
int display_width;
|
||||
int display_height;
|
||||
int pulldown; ///< TFF/RFF present
|
||||
bool interlace; ///< Progressive/interlaced (RPTFTM syntax element)
|
||||
int tfcntrflag; ///< TFCNTR present
|
||||
int psf; ///< Progressive Segmented Frame
|
||||
int pulldown; ///< TFF/RFF present
|
||||
bool interlace; ///< Progressive/interlaced (RPTFTM syntax element)
|
||||
bool tfcntrflag; ///< TFCNTR present
|
||||
int psf; ///< Progressive Segmented Frame
|
||||
int time_base_num;
|
||||
int time_base_den;
|
||||
int color_prim; ///< 8bits, chroma coordinates of the color primaries
|
||||
int transfer_char; ///< 8bits, Opto-electronic transfer characteristics
|
||||
int matrix_coef; ///< 8bits, Color primaries->YCbCr transform matrix
|
||||
int hrd_param_flag;
|
||||
int hrd_num_leaky_buckets;
|
||||
int postprocflag;
|
||||
|
||||
/* for decoding entry point */
|
||||
int panscanflag;
|
||||
int decode_entry_point();
|
||||
int extended_dmv;
|
||||
/* ------------------------*/
|
||||
|
||||
AVRational sample_aspect_ratio; // w, h
|
||||
@ -210,31 +207,11 @@ class VC1SequenceHeader : public VC1Unit
|
||||
int m_fpsFieldBitVal;
|
||||
};
|
||||
|
||||
/*
|
||||
VC1EntryPoint: public VC1Unit {
|
||||
public:
|
||||
int panscanflag;
|
||||
int loop_filter;
|
||||
int fastuvmc;
|
||||
int extended_mv;
|
||||
int dquant;
|
||||
int vstransform;
|
||||
int overlap;
|
||||
int quantizer_mode;
|
||||
int coded_width;
|
||||
int coded_height;
|
||||
int extended_dmv; ///< Additional extended dmv range at P/B frame-level
|
||||
};
|
||||
*/
|
||||
|
||||
class VC1Frame : public VC1Unit
|
||||
{
|
||||
public:
|
||||
VC1Frame() : VC1Unit(), rptfrm(0), fcm(0), rff(0), rptfrmBitPos(0) {}
|
||||
VC1Frame() : VC1Unit(), rptfrm(0), fcm(0), rff(0), tff(0), rptfrmBitPos(0), pict_type(VC1PictType::I_TYPE) {}
|
||||
int fcm;
|
||||
int interpfrm;
|
||||
int framecnt;
|
||||
int rangeredfrm;
|
||||
VC1PictType pict_type;
|
||||
int rptfrm;
|
||||
int tff;
|
||||
|
@ -17,7 +17,7 @@ void VC1StreamReader::writePESExtension(PESPacket* pesPacket, const AVPacket& av
|
||||
|
||||
pesPacket->flagsLo |= 1; // enable PES extension for VC-1 stream
|
||||
uint8_t* data = (uint8_t*)(pesPacket) + pesPacket->getHeaderLength();
|
||||
*data++ = 0x1;
|
||||
*data++ = 0x01;
|
||||
*data++ = 0x81;
|
||||
*data++ = 0x55; // VC-1 sub type id 0x55-0x5f
|
||||
pesPacket->m_pesHeaderLen += 3;
|
||||
@ -34,14 +34,14 @@ int VC1StreamReader::writeAdditionData(uint8_t* dstBuffer, uint8_t* dstEnd, AVPa
|
||||
m_firstFileFrame = false;
|
||||
if (m_seqBuffer.size() > 0)
|
||||
{
|
||||
if (dstEnd - curPtr < (int)m_seqBuffer.size())
|
||||
if ((size_t)(dstEnd - curPtr) < m_seqBuffer.size())
|
||||
THROW(ERR_COMMON, "VC1 stream error: Not enough buffer for write headers");
|
||||
memcpy(curPtr, &m_seqBuffer[0], m_seqBuffer.size());
|
||||
curPtr += m_seqBuffer.size();
|
||||
}
|
||||
if (m_entryPointBuffer.size() > 0)
|
||||
{
|
||||
if (dstEnd - curPtr < (int)m_entryPointBuffer.size())
|
||||
if ((size_t)(dstEnd - curPtr) < m_entryPointBuffer.size())
|
||||
THROW(ERR_COMMON, "VC1 stream error: Not enough buffer for write headers");
|
||||
memcpy(curPtr, &m_entryPointBuffer[0], m_entryPointBuffer.size());
|
||||
curPtr += m_entryPointBuffer.size();
|
||||
@ -56,9 +56,9 @@ int VC1StreamReader::getTSDescriptor(uint8_t* dstBuff, bool blurayMode, bool hdm
|
||||
nal = VC1Unit::findNextMarker(nal + 4, m_bufEnd))
|
||||
{
|
||||
uint8_t unitType = nal[3];
|
||||
switch (unitType)
|
||||
|
||||
if (unitType == (uint8_t)VC1Code::VC1_CODE_SEQHDR)
|
||||
{
|
||||
case VC1_CODE_SEQHDR:
|
||||
uint8_t* nextNal = VC1Unit::findNextMarker(nal + 4, m_bufEnd);
|
||||
VC1SequenceHeader sequence;
|
||||
sequence.vc1_unescape_buffer(nal + 4, nextNal - nal - 4);
|
||||
@ -66,30 +66,36 @@ int VC1StreamReader::getTSDescriptor(uint8_t* dstBuff, bool blurayMode, bool hdm
|
||||
return 0;
|
||||
|
||||
dstBuff[0] = 0x05; // registration descriptor tag
|
||||
dstBuff[1] = 6; // descriptor len
|
||||
dstBuff[1] = 0x06; // descriptor len
|
||||
dstBuff[2] = 0x56; // format identifier 0
|
||||
dstBuff[3] = 0x43; // format identifier 1
|
||||
dstBuff[4] = 0x2D; // format identifier 2
|
||||
dstBuff[5] = 0x31; // format identifier 3
|
||||
|
||||
dstBuff[6] = 0x01; // profile and level subdescriptor
|
||||
if (sequence.profile == 0)
|
||||
dstBuff[7] = (sequence.profile << 4) + 0x11 + (sequence.level >> 1);
|
||||
else if (sequence.profile == 1)
|
||||
dstBuff[7] = (sequence.profile << 4) + 0x41 + (sequence.level >> 1);
|
||||
else if (sequence.profile == 3)
|
||||
dstBuff[7] = (sequence.profile << 4) + 0x61 + sequence.level;
|
||||
else
|
||||
dstBuff[1] -= 2; // remove profile and level descriptor
|
||||
return dstBuff[1] + 2;
|
||||
|
||||
break;
|
||||
int profile = (int)sequence.profile << 4;
|
||||
switch (sequence.profile)
|
||||
{
|
||||
case Profile::PROFILE_SIMPLE:
|
||||
dstBuff[7] = profile + 0x11 + (sequence.level >> 1);
|
||||
break;
|
||||
case Profile::PROFILE_MAIN:
|
||||
dstBuff[7] = profile + 0x41 + (sequence.level >> 1);
|
||||
break;
|
||||
case Profile::PROFILE_ADVANCED:
|
||||
dstBuff[7] = profile + 0x61 + sequence.level;
|
||||
break;
|
||||
default:
|
||||
dstBuff[1] -= 2; // remove profile and level descriptor
|
||||
return 6;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool VC1StreamReader::skipNal(uint8_t* nal) { return !m_eof && nal[0] == VC1_CODE_ENDOFSEQ; }
|
||||
bool VC1StreamReader::skipNal(uint8_t* nal) { return !m_eof && nal[0] == (uint8_t)VC1Code::VC1_CODE_ENDOFSEQ; }
|
||||
|
||||
CheckStreamRez VC1StreamReader::checkStream(uint8_t* buffer, int len)
|
||||
{
|
||||
@ -105,16 +111,16 @@ CheckStreamRez VC1StreamReader::checkStream(uint8_t* buffer, int len)
|
||||
uint8_t unitType = nal[3];
|
||||
switch (unitType)
|
||||
{
|
||||
case VC1_CODE_ENDOFSEQ:
|
||||
case (uint8_t)VC1Code::VC1_CODE_ENDOFSEQ:
|
||||
break;
|
||||
case VC1_CODE_SLICE:
|
||||
case VC1_USER_CODE_SLICE:
|
||||
case (uint8_t)VC1Code::VC1_CODE_SLICE:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_SLICE:
|
||||
break;
|
||||
case VC1_CODE_FIELD:
|
||||
case VC1_USER_CODE_FIELD:
|
||||
case (uint8_t)VC1Code::VC1_CODE_FIELD:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_FIELD:
|
||||
break;
|
||||
case VC1_CODE_FRAME:
|
||||
case VC1_USER_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_FRAME:
|
||||
nextNal = VC1Unit::findNextMarker(nal + 4, end);
|
||||
if (m_frame.decode_frame_direct(m_sequence, nal + 4, nextNal) != 0)
|
||||
break;
|
||||
@ -132,15 +138,15 @@ CheckStreamRez VC1StreamReader::checkStream(uint8_t* buffer, int len)
|
||||
if (m_frame.pict_type == VC1PictType::I_TYPE)
|
||||
iFrameFound = true;
|
||||
break;
|
||||
case VC1_CODE_ENTRYPOINT:
|
||||
case VC1_USER_CODE_ENTRYPOINT:
|
||||
case (uint8_t)VC1Code::VC1_CODE_ENTRYPOINT:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_ENTRYPOINT:
|
||||
nextNal = VC1Unit::findNextMarker(nal + 4, end);
|
||||
m_sequence.vc1_unescape_buffer(nal + 4, nextNal - nal - 4);
|
||||
if (m_sequence.decode_entry_point() != 0)
|
||||
break;
|
||||
break;
|
||||
case VC1_CODE_SEQHDR:
|
||||
case VC1_USER_CODE_SEQHDR:
|
||||
case (uint8_t)VC1Code::VC1_CODE_SEQHDR:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_SEQHDR:
|
||||
nextNal = VC1Unit::findNextMarker(nal + 4, end);
|
||||
m_sequence.vc1_unescape_buffer(nal + 4, nextNal - nal - 4);
|
||||
if (m_sequence.decode_sequence_header() != 0)
|
||||
@ -169,15 +175,15 @@ int VC1StreamReader::intDecodeNAL(uint8_t* buff)
|
||||
uint8_t* nextNal = 0;
|
||||
switch (*buff)
|
||||
{
|
||||
case VC1_CODE_ENTRYPOINT:
|
||||
case (uint8_t)VC1Code::VC1_CODE_ENTRYPOINT:
|
||||
return decodeEntryPoint(buff);
|
||||
break;
|
||||
case VC1_CODE_ENDOFSEQ:
|
||||
case (uint8_t)VC1Code::VC1_CODE_ENDOFSEQ:
|
||||
nextNal = VC1Unit::findNextMarker(buff, m_bufEnd) + 3;
|
||||
if (!m_eof && nextNal >= m_bufEnd)
|
||||
return NOT_ENOUGH_BUFFER;
|
||||
break;
|
||||
case VC1_CODE_SEQHDR:
|
||||
case (uint8_t)VC1Code::VC1_CODE_SEQHDR:
|
||||
m_spsPpsFound = true;
|
||||
rez = decodeSeqHeader(buff);
|
||||
if (rez != 0)
|
||||
@ -189,13 +195,13 @@ int VC1StreamReader::intDecodeNAL(uint8_t* buff)
|
||||
return NOT_ENOUGH_BUFFER;
|
||||
switch (*nextNal)
|
||||
{
|
||||
case VC1_CODE_ENTRYPOINT:
|
||||
case (uint8_t)VC1Code::VC1_CODE_ENTRYPOINT:
|
||||
rez = decodeEntryPoint(nextNal);
|
||||
if (rez != 0)
|
||||
return rez;
|
||||
break;
|
||||
case VC1_CODE_FRAME:
|
||||
case VC1_USER_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_FRAME:
|
||||
rez = decodeFrame(nextNal);
|
||||
if (rez == 0)
|
||||
{
|
||||
@ -208,8 +214,8 @@ int VC1StreamReader::intDecodeNAL(uint8_t* buff)
|
||||
}
|
||||
// m_lastIFrame = true;
|
||||
break;
|
||||
case VC1_CODE_FRAME:
|
||||
case VC1_USER_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_CODE_FRAME:
|
||||
case (uint8_t)VC1Code::VC1_USER_CODE_FRAME:
|
||||
m_decodedAfterSeq = false;
|
||||
rez = decodeFrame(buff);
|
||||
return rez;
|
||||
@ -225,8 +231,8 @@ int VC1StreamReader::decodeSeqHeader(uint8_t* buff)
|
||||
{
|
||||
return NOT_ENOUGH_BUFFER;
|
||||
}
|
||||
int oldSpsLen = nextNal - buff - 1;
|
||||
m_sequence.vc1_unescape_buffer(buff + 1, nextNal - buff - 1);
|
||||
size_t oldSpsLen = (size_t)(nextNal - buff - 1);
|
||||
m_sequence.vc1_unescape_buffer(buff + 1, oldSpsLen);
|
||||
int rez = m_sequence.decode_sequence_header();
|
||||
if (rez != 0)
|
||||
return rez;
|
||||
@ -238,7 +244,7 @@ int VC1StreamReader::decodeSeqHeader(uint8_t* buff)
|
||||
{
|
||||
LTRACE(LT_INFO, 2, "Decoding VC-1 stream (track " << m_streamIndex << "): " << m_sequence.getStreamDescr());
|
||||
}
|
||||
if (m_sequence.profile != PROFILE_ADVANCED)
|
||||
if (m_sequence.profile != Profile::PROFILE_ADVANCED)
|
||||
THROW(ERR_VC1_ERR_PROFILE,
|
||||
"Only ADVANCED profile are supported now. For feature request contat to: r_vasilenko@smlabs.net.");
|
||||
|
||||
@ -283,7 +289,7 @@ int VC1StreamReader::decodeFrame(uint8_t* buff)
|
||||
{
|
||||
if (!m_sequence.interlace || m_sequence.psf)
|
||||
{
|
||||
m_prevDtsInc = pcrIncVal * (m_frame.rptfrm + 1);
|
||||
m_prevDtsInc = pcrIncVal * ((int64_t)m_frame.rptfrm + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -354,10 +360,10 @@ int VC1StreamReader::getNextBFrames(uint8_t* buffer, int64_t& bTiming)
|
||||
for (uint8_t* nal = VC1Unit::findNextMarker(buffer, m_bufEnd); nal < m_bufEnd - 4;
|
||||
nal = VC1Unit::findNextMarker(nal + 4, m_bufEnd))
|
||||
{
|
||||
if (nal[3] != VC1_CODE_FIELD && nal[3] != VC1_USER_CODE_FIELD)
|
||||
if (nal[3] != (uint8_t)VC1Code::VC1_CODE_FIELD && nal[3] != (uint8_t)VC1Code::VC1_USER_CODE_FIELD)
|
||||
m_nextFrameAddr = nal;
|
||||
|
||||
if (nal[3] == VC1_CODE_FRAME || nal[3] == VC1_USER_CODE_FRAME)
|
||||
if (nal[3] == (uint8_t)VC1Code::VC1_CODE_FRAME || nal[3] == (uint8_t)VC1Code::VC1_USER_CODE_FRAME)
|
||||
{
|
||||
VC1Frame frame;
|
||||
if (frame.decode_frame_direct(m_sequence, nal + 4, m_bufEnd) != 0)
|
||||
@ -368,13 +374,13 @@ int VC1StreamReader::getNextBFrames(uint8_t* buffer, int64_t& bTiming)
|
||||
|
||||
int64_t pcrIncVal = m_pcrIncPerFrame;
|
||||
// if (frame.fcm == 2) // coded field
|
||||
// pcrIncVal = m_pcrIncPerField;
|
||||
// pcrIncVal = m_pcrIncPerField;
|
||||
|
||||
if (m_sequence.pulldown)
|
||||
{
|
||||
if (!m_sequence.interlace || m_sequence.psf)
|
||||
{
|
||||
pcrIncVal = pcrIncVal * (frame.rptfrm + 1);
|
||||
pcrIncVal = pcrIncVal * ((int64_t)frame.rptfrm + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -404,7 +410,7 @@ uint8_t* VC1StreamReader::findNextFrame(uint8_t* buffer)
|
||||
for (uint8_t* nal = VC1Unit::findNextMarker(buffer, m_bufEnd); nal < m_bufEnd - 4;
|
||||
nal = VC1Unit::findNextMarker(nal + 4, m_bufEnd))
|
||||
{
|
||||
if (nal[3] != VC1_CODE_FIELD && nal[3] != VC1_USER_CODE_FIELD)
|
||||
if (nal[3] != (uint8_t)VC1Code::VC1_CODE_FIELD && nal[3] != (uint8_t)VC1Code::VC1_USER_CODE_FIELD)
|
||||
return nal;
|
||||
}
|
||||
if (m_eof)
|
||||
@ -415,8 +421,6 @@ uint8_t* VC1StreamReader::findNextFrame(uint8_t* buffer)
|
||||
|
||||
void VC1StreamReader::updateStreamFps(void* nalUnit, uint8_t* buff, uint8_t* nextNal, int oldSpsLen)
|
||||
{
|
||||
// SPSUnit* sps = (SPSUnit*) nalUnit;
|
||||
// sps->setFps(m_fps);
|
||||
m_sequence.setFPS(m_fps);
|
||||
uint8_t* tmpBuffer = new uint8_t[oldSpsLen + 16];
|
||||
long newSpsLen = m_sequence.vc1_escape_buffer(tmpBuffer);
|
||||
@ -425,7 +429,6 @@ void VC1StreamReader::updateStreamFps(void* nalUnit, uint8_t* buff, uint8_t* nex
|
||||
int sizeDiff = newSpsLen - oldSpsLen;
|
||||
memmove(nextNal + sizeDiff, nextNal, m_bufEnd - nextNal);
|
||||
m_bufEnd += sizeDiff;
|
||||
// m_dataLen += sizeDiff;
|
||||
}
|
||||
memcpy(buff + 1, tmpBuffer, newSpsLen);
|
||||
delete[] tmpBuffer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user