diff options
Diffstat (limited to 'xbmc/utils/VC1BitstreamParser.cpp')
-rw-r--r-- | xbmc/utils/VC1BitstreamParser.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/xbmc/utils/VC1BitstreamParser.cpp b/xbmc/utils/VC1BitstreamParser.cpp new file mode 100644 index 0000000..8ac1b6e --- /dev/null +++ b/xbmc/utils/VC1BitstreamParser.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VC1BitstreamParser.h" + +#include "BitstreamReader.h" + +enum +{ + VC1_PROFILE_SIMPLE, + VC1_PROFILE_MAIN, + VC1_PROFILE_RESERVED, + VC1_PROFILE_ADVANCED, + VC1_PROFILE_NOPROFILE +}; + +enum +{ + VC1_END_OF_SEQ = 0x0A, + VC1_SLICE = 0x0B, + VC1_FIELD = 0x0C, + VC1_FRAME = 0x0D, + VC1_ENTRYPOINT = 0x0E, + VC1_SEQUENCE = 0x0F, + VC1_SLICE_USER = 0x1B, + VC1_FIELD_USER = 0x1C, + VC1_FRAME_USER = 0x1D, + VC1_ENTRY_POINT_USER = 0x1E, + VC1_SEQUENCE_USER = 0x1F +}; + +enum +{ + VC1_FRAME_PROGRESSIVE = 0x0, + VC1_FRAME_INTERLACE = 0x10, + VC1_FIELD_INTERLACE = 0x11 +}; + +CVC1BitstreamParser::CVC1BitstreamParser() +{ + Reset(); +} + +void CVC1BitstreamParser::Reset() +{ + m_Profile = VC1_PROFILE_NOPROFILE; +} + +bool CVC1BitstreamParser::IsRecoveryPoint(const uint8_t *buf, int buf_size) +{ + return vc1_parse_frame(buf, buf + buf_size, true); +}; + +bool CVC1BitstreamParser::IsIFrame(const uint8_t *buf, int buf_size) +{ + return vc1_parse_frame(buf, buf + buf_size, false); +}; + +bool CVC1BitstreamParser::vc1_parse_frame(const uint8_t *buf, const uint8_t *buf_end, bool sequence_only) +{ + uint32_t state = -1; + for (;;) + { + buf = find_start_code(buf, buf_end, &state); + if (buf >= buf_end) + break; + if (buf[-1] == VC1_SEQUENCE) + { + if (m_Profile != VC1_PROFILE_NOPROFILE) + return false; + CBitstreamReader br(buf, buf_end - buf); + // Read the profile + m_Profile = static_cast<uint8_t>(br.ReadBits(2)); + if (m_Profile == VC1_PROFILE_ADVANCED) + { + br.SkipBits(39); + m_AdvInterlace = br.ReadBits(1); + } + else + { + br.SkipBits(22); + + m_SimpleSkipBits = 2; + if (br.ReadBits(1)) //rangered + ++m_SimpleSkipBits; + + m_MaxBFrames = br.ReadBits(3); + + br.SkipBits(2); // quantizer + if (br.ReadBits(1)) //finterpflag + ++m_SimpleSkipBits; + } + if (sequence_only) + return true; + } + else if (buf[-1] == VC1_FRAME) + { + CBitstreamReader br(buf, buf_end - buf); + + if (sequence_only) + return false; + if (m_Profile == VC1_PROFILE_ADVANCED) + { + uint8_t fcm; + if (m_AdvInterlace) { + fcm = br.ReadBits(1); + if (fcm) + fcm = br.ReadBits(1) + 1; + } + else + fcm = VC1_FRAME_PROGRESSIVE; + if (fcm == VC1_FIELD_INTERLACE) { + uint8_t pic = br.ReadBits(3); + return pic == 0x00 || pic == 0x01; + } + else + { + uint8_t pic(0); + while (pic < 4 && br.ReadBits(1))++pic; + return pic == 2; + } + return false; + } + else if (m_Profile != VC1_PROFILE_NOPROFILE) + { + br.SkipBits(m_SimpleSkipBits); // quantizer + uint8_t pic(br.ReadBits(1)); + if (m_MaxBFrames) { + if (!pic) { + pic = br.ReadBits(1); + return pic != 0; + } + else + return false; + } + else + return pic != 0; + } + else + break; + } + } + return false; +} |