Merge pull request #26166 from ksooo/improve-plugin-ctx-menus
[xbmc.git] / xbmc / utils / VC1BitstreamParser.cpp
blob8ac1b6e0dcb8725eb310d36e4f79b9d75a83ceee
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VC1BitstreamParser.h"
11 #include "BitstreamReader.h"
13 enum
15 VC1_PROFILE_SIMPLE,
16 VC1_PROFILE_MAIN,
17 VC1_PROFILE_RESERVED,
18 VC1_PROFILE_ADVANCED,
19 VC1_PROFILE_NOPROFILE
22 enum
24 VC1_END_OF_SEQ = 0x0A,
25 VC1_SLICE = 0x0B,
26 VC1_FIELD = 0x0C,
27 VC1_FRAME = 0x0D,
28 VC1_ENTRYPOINT = 0x0E,
29 VC1_SEQUENCE = 0x0F,
30 VC1_SLICE_USER = 0x1B,
31 VC1_FIELD_USER = 0x1C,
32 VC1_FRAME_USER = 0x1D,
33 VC1_ENTRY_POINT_USER = 0x1E,
34 VC1_SEQUENCE_USER = 0x1F
37 enum
39 VC1_FRAME_PROGRESSIVE = 0x0,
40 VC1_FRAME_INTERLACE = 0x10,
41 VC1_FIELD_INTERLACE = 0x11
44 CVC1BitstreamParser::CVC1BitstreamParser()
46 Reset();
49 void CVC1BitstreamParser::Reset()
51 m_Profile = VC1_PROFILE_NOPROFILE;
54 bool CVC1BitstreamParser::IsRecoveryPoint(const uint8_t *buf, int buf_size)
56 return vc1_parse_frame(buf, buf + buf_size, true);
59 bool CVC1BitstreamParser::IsIFrame(const uint8_t *buf, int buf_size)
61 return vc1_parse_frame(buf, buf + buf_size, false);
64 bool CVC1BitstreamParser::vc1_parse_frame(const uint8_t *buf, const uint8_t *buf_end, bool sequence_only)
66 uint32_t state = -1;
67 for (;;)
69 buf = find_start_code(buf, buf_end, &state);
70 if (buf >= buf_end)
71 break;
72 if (buf[-1] == VC1_SEQUENCE)
74 if (m_Profile != VC1_PROFILE_NOPROFILE)
75 return false;
76 CBitstreamReader br(buf, buf_end - buf);
77 // Read the profile
78 m_Profile = static_cast<uint8_t>(br.ReadBits(2));
79 if (m_Profile == VC1_PROFILE_ADVANCED)
81 br.SkipBits(39);
82 m_AdvInterlace = br.ReadBits(1);
84 else
86 br.SkipBits(22);
88 m_SimpleSkipBits = 2;
89 if (br.ReadBits(1)) //rangered
90 ++m_SimpleSkipBits;
92 m_MaxBFrames = br.ReadBits(3);
94 br.SkipBits(2); // quantizer
95 if (br.ReadBits(1)) //finterpflag
96 ++m_SimpleSkipBits;
98 if (sequence_only)
99 return true;
101 else if (buf[-1] == VC1_FRAME)
103 CBitstreamReader br(buf, buf_end - buf);
105 if (sequence_only)
106 return false;
107 if (m_Profile == VC1_PROFILE_ADVANCED)
109 uint8_t fcm;
110 if (m_AdvInterlace) {
111 fcm = br.ReadBits(1);
112 if (fcm)
113 fcm = br.ReadBits(1) + 1;
115 else
116 fcm = VC1_FRAME_PROGRESSIVE;
117 if (fcm == VC1_FIELD_INTERLACE) {
118 uint8_t pic = br.ReadBits(3);
119 return pic == 0x00 || pic == 0x01;
121 else
123 uint8_t pic(0);
124 while (pic < 4 && br.ReadBits(1))++pic;
125 return pic == 2;
127 return false;
129 else if (m_Profile != VC1_PROFILE_NOPROFILE)
131 br.SkipBits(m_SimpleSkipBits); // quantizer
132 uint8_t pic(br.ReadBits(1));
133 if (m_MaxBFrames) {
134 if (!pic) {
135 pic = br.ReadBits(1);
136 return pic != 0;
138 else
139 return false;
141 else
142 return pic != 0;
144 else
145 break;
148 return false;