summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/BitstreamReader.cpp
blob: 6f2a7ffabecf1cbe628f8d21d6e386a4bbfa7f67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 *  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 "BitstreamReader.h"

CBitstreamReader::CBitstreamReader(const uint8_t *buf, int len)
  : buffer(buf)
  , start(buf)
  , offbits(0)
  , length(len)
  , oflow(0)
{
}

uint32_t CBitstreamReader::ReadBits(int nbits)
{
  uint32_t ret = GetBits(nbits);

  offbits += nbits;
  buffer += offbits / 8;
  offbits %= 8;

  return ret;
}

void CBitstreamReader::SkipBits(int nbits)
{
  offbits += nbits;
  buffer += offbits / 8;
  offbits %= 8;

  if (buffer > (start + length))
    oflow = 1;
}

uint32_t CBitstreamReader::GetBits(int nbits)
{
  int i, nbytes;
  uint32_t ret = 0;
  const uint8_t *buf;

  buf = buffer;
  nbytes = (offbits + nbits) / 8;

  if (((offbits + nbits) % 8) > 0)
    nbytes++;

  if ((buf + nbytes) > (start + length))
  {
    oflow = 1;
    return 0;
  }
  for (i = 0; i<nbytes; i++)
    ret += buf[i] << ((nbytes - i - 1) * 8);

  i = (4 - nbytes) * 8 + offbits;

  ret = ((ret << i) >> i) >> ((nbytes * 8) - nbits - offbits);

  return ret;
}

const uint8_t* find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state)
{
  if (p >= end)
    return end;

  for (int i = 0; i < 3; i++)
  {
    uint32_t tmp = *state << 8;
    *state = tmp + *(p++);
    if (tmp == 0x100 || p == end)
      return p;
  }

  while (p < end)
  {
    if (p[-1] > 1) p += 3;
    else if (p[-2]) p += 2;
    else if (p[-3] | (p[-1] - 1)) p++;
    else {
      p++;
      break;
    }
  }

  p = (p < end)? p - 4 : end - 4;
  *state = BS_RB32(p);

  return p + 4;
}