1473 lines
69 KiB
C++
1473 lines
69 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <cassert>
|
|
#include "h263_information.h"
|
|
|
|
namespace webrtc {
|
|
// MCBPC ---
|
|
static const WebRtc_Word32 MCBPC_I_MAX_CODE_LENGTH = 2;
|
|
static const WebRtc_Word32 MCBPC_I_TABLE_LENGTH = 9;
|
|
static const WebRtc_UWord8 MCBPC_I_CODE[9][2] = {{0x80,0x00}, //1
|
|
{0x20,0x00}, //001
|
|
{0x40,0x00}, //010
|
|
{0x60,0x00}, //011
|
|
{0x10,0x00}, //0001
|
|
{0x04,0x00}, //0000 01
|
|
{0x08,0x00}, //0000 10
|
|
{0x0C,0x00}, //0000 11
|
|
{0x00,0x80}}; //0000 0000 1
|
|
|
|
static const WebRtc_UWord8 MCBPC_I_MASK[9][2] = {{0x80,0x00}, //1
|
|
{0xE0,0x00}, //001
|
|
{0xE0,0x00}, //010
|
|
{0xE0,0x00}, //011
|
|
{0xF0,0x00}, //0001
|
|
{0xFC,0x00}, //0000 01
|
|
{0xFC,0x00}, //0000 10
|
|
{0xFC,0x00}, //0000 11
|
|
{0xFF,0x80}}; //0000 0000 1
|
|
|
|
static const WebRtc_Word32 MCBPC_I_MBTYPE[9] = {3,3,3,3,4,4,4,4,6};
|
|
static const WebRtc_Word32 MCBPC_I_SIZE[9] = {1,3,3,3,4,6,6,6,9};
|
|
static const char MCBPC_I_CBPC[9][2] = {{0,0},{0,1},{1,0},{1,1},{0,0},{0,1},{1,0},{1,1},{0,0}};
|
|
|
|
static const WebRtc_Word32 MCBPC_P_MAX_CODE_LENGTH = 2;
|
|
static const WebRtc_Word32 MCBPC_P_TABLE_LENGTH = 25;
|
|
static const WebRtc_UWord8 MCBPC_P_CODE[25][2] = {{0x80,0x00}, //1
|
|
{0x30,0x00}, //0011
|
|
{0x20,0x00}, //0010
|
|
{0x14,0x00}, //0001 01
|
|
{0x60,0x00}, //011
|
|
{0x0E,0x00}, //0000 111
|
|
{0x0C,0x00}, //0000 110
|
|
{0x02,0x80}, //0000 0010 1
|
|
{0x40,0x00}, //010
|
|
{0x0A,0x00}, //0000 101
|
|
{0x08,0x00}, //0000 100
|
|
{0x05,0x00}, //0000 0101
|
|
{0x18,0x00}, //0001 1
|
|
{0x04,0x00}, //0000 0100
|
|
{0x03,0x00}, //0000 0011
|
|
{0x06,0x00}, //0000 011
|
|
{0x10,0x00}, //0001 00
|
|
{0x02,0x00}, //0000 0010 0
|
|
{0x01,0x80}, //0000 0001 1
|
|
{0x01,0x00}, //0000 0001 0
|
|
{0x00,0x80}, //0000 0000 1
|
|
{0x00,0x40}, //0000 0000 010
|
|
{0x00,0x60}, //0000 0000 0110 0
|
|
{0x00,0x70}, //0000 0000 0111 0
|
|
{0x00,0x78}}; //0000 0000 0111 1
|
|
|
|
static const WebRtc_UWord8 MCBPC_P_MASK[25][2] = {{0x80,0x00}, //1
|
|
{0xF0,0x00}, //0011
|
|
{0xF0,0x00}, //0010
|
|
{0xFC,0x00}, //0001 01
|
|
{0xE0,0x00}, //011
|
|
{0xFE,0x00}, //0000 111
|
|
{0xFE,0x00}, //0000 110
|
|
{0xFF,0x80}, //0000 0010 1
|
|
{0xE0,0x00}, //010
|
|
{0xFE,0x00}, //0000 101
|
|
{0xFE,0x00}, //0000 100
|
|
{0xFF,0x00}, //0000 0101
|
|
{0xF8,0x00}, //0001 1
|
|
{0xFF,0x00}, //0000 0100
|
|
{0xFF,0x00}, //0000 0011
|
|
{0xFE,0x00}, //0000 011
|
|
{0xFC,0x00}, //0001 00
|
|
{0xFF,0x80}, //0000 0010 0
|
|
{0xFF,0x80}, //0000 0001 1
|
|
{0xFF,0x80}, //0000 0001 0
|
|
{0xFF,0x80}, //0000 0000 1
|
|
{0xFF,0xE0}, //0000 0000 010
|
|
{0xFF,0xF8}, //0000 0000 0110 0
|
|
{0xFF,0xF8}, //0000 0000 0111 0
|
|
{0xFF,0xF8}}; //0000 0000 0111 1
|
|
|
|
static const WebRtc_Word32 MCBPC_P_MBTYPE[25] = {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,6, 5, 5, 5, 5};
|
|
static const WebRtc_Word32 MCBPC_P_SIZE[25] = {1,4,4,6,3,7,7,9,3,7,7,8,5,8,8,7,6,9,9,9,9,11,13,13,13};
|
|
static const char MCBPC_P_CBPC[25][2] = {{0,0},{0,1},{1,0},{1,1},
|
|
{0,0},{0,1},{1,0},{1,1},
|
|
{0,0},{0,1},{1,0},{1,1},
|
|
{0,0},{0,1},{1,0},{1,1},
|
|
{0,0},{0,1},{1,0},{1,1},
|
|
{0,0},
|
|
{0,0},{0,1},{1,0},{1,1}};
|
|
|
|
// CBPY ---
|
|
static const WebRtc_Word32 CBPY_MAX_CODE_LENGTH = 1;
|
|
static const WebRtc_Word32 CBPY_TABLE_LENGTH = 16;
|
|
static const WebRtc_UWord8 CBPY_CODE[16][1] = {{0x30}, //0011
|
|
{0x28}, //0010 1
|
|
{0x20}, //0010 0
|
|
{0x90}, //1001
|
|
{0x18}, //0001 1
|
|
{0x70}, //0111
|
|
{0x08}, //0000 10
|
|
{0xB0}, //1011
|
|
{0x10}, //0001 0
|
|
{0x0C}, //0000 11
|
|
{0x50}, //0101
|
|
{0xA0}, //1010
|
|
{0x40}, //0100
|
|
{0x80}, //1000
|
|
{0x60}, //0110
|
|
{0xC0}}; //11
|
|
|
|
static const WebRtc_UWord8 CBPY_MASK[16][1] = {{0xF0}, //0011
|
|
{0xF8}, //0010 1
|
|
{0xF8}, //0010 0
|
|
{0xF0}, //1001
|
|
{0xF8}, //0001 1
|
|
{0xF0}, //0111
|
|
{0xFC}, //0000 10
|
|
{0xF0}, //1011
|
|
{0xF8}, //0001 0
|
|
{0xFC}, //0000 11
|
|
{0xF0}, //0101
|
|
{0xF0}, //1010
|
|
{0xF0}, //0100
|
|
{0xF0}, //1000
|
|
{0xF0}, //0110
|
|
{0xC0}}; //11
|
|
|
|
static const WebRtc_Word32 CBPY_SIZE[16] = {4,5,5,4,5,4,6,4,5,6,4,4,4,4,4,2};
|
|
static const char CBPY_CBPY[16][4] = {{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},
|
|
{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},
|
|
{1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},
|
|
{1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1}};
|
|
|
|
// MVD ---
|
|
static const WebRtc_Word32 MVD_MAX_CODE_LENGTH = 2;
|
|
static const WebRtc_Word32 MVD_TABLE_LENGTH = 64;
|
|
static const WebRtc_UWord8 MVD_CODE[64][2] = {{0x00,0x28}, //0000 0000 0010 1
|
|
{0x00,0x38}, //0000 0000 0011 1
|
|
{0x00,0x50}, //0000 0000 0101
|
|
{0x00,0x70}, //0000 0000 0111
|
|
{0x00,0x90}, //0000 0000 1001
|
|
{0x00,0xB0}, //0000 0000 1011
|
|
{0x00,0xD0}, //0000 0000 1101
|
|
{0x00,0xF0}, //0000 0000 1111
|
|
{0x01,0x20}, //0000 0001 001
|
|
{0x01,0x60}, //0000 0001 011
|
|
{0x01,0xA0}, //0000 0001 101
|
|
{0x01,0xE0}, //0000 0001 111
|
|
{0x02,0x20}, //0000 0010 001
|
|
{0x02,0x60}, //0000 0010 011
|
|
{0x02,0xA0}, //0000 0010 101
|
|
{0x02,0xE0}, //0000 0010 111
|
|
{0x03,0x20}, //0000 0011 001
|
|
{0x03,0x60}, //0000 0011 011
|
|
{0x03,0xA0}, //0000 0011 101
|
|
{0x03,0xE0}, //0000 0011 111
|
|
{0x04,0x20}, //0000 0100 001
|
|
{0x04,0x60}, //0000 0100 011
|
|
{0x04,0xC0}, //0000 0100 11
|
|
{0x05,0x40}, //0000 0101 01
|
|
{0x05,0xC0}, //0000 0101 11
|
|
{0x07,0x00}, //0000 0111
|
|
{0x09,0x00}, //0000 1001
|
|
{0x0B,0x00}, //0000 1011
|
|
{0x0E,0x00}, //0000 111
|
|
{0x18,0x00}, //0001 1
|
|
{0x30,0x00}, //0011
|
|
{0x60,0x00}, //011
|
|
{0x80,0x00}, //1
|
|
{0x40,0x00}, //010
|
|
{0x20,0x00}, //0010
|
|
{0x10,0x00}, //0001 0
|
|
{0x0C,0x00}, //0000 110
|
|
{0x0A,0x00}, //0000 1010
|
|
{0x08,0x00}, //0000 1000
|
|
{0x06,0x00}, //0000 0110
|
|
{0x05,0x80}, //0000 0101 10
|
|
{0x05,0x00}, //0000 0101 00
|
|
{0x04,0x80}, //0000 0100 10
|
|
{0x04,0x40}, //0000 0100 010
|
|
{0x04,0x00}, //0000 0100 000
|
|
{0x03,0xC0}, //0000 0011 110
|
|
{0x03,0x80}, //0000 0011 100
|
|
{0x03,0x40}, //0000 0011 010
|
|
{0x03,0x00}, //0000 0011 000
|
|
{0x02,0xC0}, //0000 0010 110
|
|
{0x02,0x80}, //0000 0010 100
|
|
{0x02,0x40}, //0000 0010 010
|
|
{0x02,0x00}, //0000 0010 000
|
|
{0x01,0xC0}, //0000 0001 110
|
|
{0x01,0x80}, //0000 0001 100
|
|
{0x01,0x40}, //0000 0001 010
|
|
{0x01,0x00}, //0000 0001 000
|
|
{0x00,0xE0}, //0000 0000 1110
|
|
{0x00,0xC0}, //0000 0000 1100
|
|
{0x00,0xA0}, //0000 0000 1010
|
|
{0x00,0x80}, //0000 0000 1000
|
|
{0x00,0x60}, //0000 0000 0110
|
|
{0x00,0x40}, //0000 0000 0100
|
|
{0x00,0x30}}; //0000 0000 0011 0
|
|
|
|
static const WebRtc_UWord8 MVD_MASK[64][2] = {{0xFF,0xF8}, //0000 0000 0010 1
|
|
{0xFF,0xF8}, //0000 0000 0011 1
|
|
{0xFF,0xF0}, //0000 0000 0101
|
|
{0xFF,0xF0}, //0000 0000 0111
|
|
{0xFF,0xF0}, //0000 0000 1001
|
|
{0xFF,0xF0}, //0000 0000 1011
|
|
{0xFF,0xF0}, //0000 0000 1101
|
|
{0xFF,0xF0}, //0000 0000 1111
|
|
{0xFF,0xE0}, //0000 0001 001
|
|
{0xFF,0xE0}, //0000 0001 011
|
|
{0xFF,0xE0}, //0000 0001 101
|
|
{0xFF,0xE0}, //0000 0001 111
|
|
{0xFF,0xE0}, //0000 0010 001
|
|
{0xFF,0xE0}, //0000 0010 011
|
|
{0xFF,0xE0}, //0000 0010 101
|
|
{0xFF,0xE0}, //0000 0010 111
|
|
{0xFF,0xE0}, //0000 0011 001
|
|
{0xFF,0xE0}, //0000 0011 011
|
|
{0xFF,0xE0}, //0000 0011 101
|
|
{0xFF,0xE0}, //0000 0011 111
|
|
{0xFF,0xE0}, //0000 0100 001
|
|
{0xFF,0xE0}, //0000 0100 011
|
|
{0xFF,0xC0}, //0000 0100 11
|
|
{0xFF,0xC0}, //0000 0101 01
|
|
{0xFF,0xC0}, //0000 0101 11
|
|
{0xFF,0x00}, //0000 0111
|
|
{0xFF,0x00}, //0000 1001
|
|
{0xFF,0x00}, //0000 1011
|
|
{0xFE,0x00}, //0000 111
|
|
{0xF8,0x00}, //0001 1
|
|
{0xF0,0x00}, //0011
|
|
{0xE0,0x00}, //011
|
|
{0x80,0x00}, //1
|
|
{0xE0,0x00}, //010
|
|
{0xF0,0x00}, //0010
|
|
{0xF8,0x00}, //0001 0
|
|
{0xFE,0x00}, //0000 110
|
|
{0xFF,0x00}, //0000 1010
|
|
{0xFF,0x00}, //0000 1000
|
|
{0xFF,0x00}, //0000 0110
|
|
{0xFF,0xC0}, //0000 0101 10
|
|
{0xFF,0xC0}, //0000 0101 00
|
|
{0xFF,0xC0}, //0000 0100 10
|
|
{0xFF,0xE0}, //0000 0100 010
|
|
{0xFF,0xE0}, //0000 0100 000
|
|
{0xFF,0xE0}, //0000 0011 110
|
|
{0xFF,0xE0}, //0000 0011 100
|
|
{0xFF,0xE0}, //0000 0011 010
|
|
{0xFF,0xE0}, //0000 0011 000
|
|
{0xFF,0xE0}, //0000 0010 110
|
|
{0xFF,0xE0}, //0000 0010 100
|
|
{0xFF,0xE0}, //0000 0010 010
|
|
{0xFF,0xE0}, //0000 0010 000
|
|
{0xFF,0xE0}, //0000 0001 110
|
|
{0xFF,0xE0}, //0000 0001 100
|
|
{0xFF,0xE0}, //0000 0001 010
|
|
{0xFF,0xE0}, //0000 0001 000
|
|
{0xFF,0xF0}, //0000 0000 1110
|
|
{0xFF,0xF0}, //0000 0000 1100
|
|
{0xFF,0xF0}, //0000 0000 1010
|
|
{0xFF,0xF0}, //0000 0000 1000
|
|
{0xFF,0xF0}, //0000 0000 0110
|
|
{0xFF,0xF0}, //0000 0000 0100
|
|
{0xFF,0xF8}}; //0000 0000 0011 0
|
|
|
|
static const WebRtc_Word32 MVD_SIZE[64] = {13,13,12,12,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,
|
|
11,11,10,10,10, 8, 8, 8, 7, 5, 4, 3, 1, 3, 4, 5, 7, 8, 8, 8,
|
|
10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,
|
|
12,12,12,13};
|
|
|
|
// TCOEF ---
|
|
static const WebRtc_Word32 TCOEF_MAX_CODE_LENGTH = 2;
|
|
static const WebRtc_Word32 TCOEF_TABLE_LENGTH = 103;
|
|
static const WebRtc_UWord8 TCOEF_CODE[103][2] = {{0x80,0x00}, //10s
|
|
{0xF0,0x00}, //1111s
|
|
{0x54,0x00}, //0101 01s
|
|
{0x2E,0x00}, //0010 111s
|
|
{0x1F,0x00}, //0001 1111s
|
|
{0x12,0x80}, //0001 0010 1s
|
|
{0x12,0x00}, //0001 0010 0s
|
|
{0x08,0x40}, //0000 1000 01s
|
|
{0x08,0x00}, //0000 1000 00s
|
|
{0x00,0xE0}, //0000 0000 111s
|
|
{0x00,0xC0}, //0000 0000 110s
|
|
{0x04,0x00}, //0000 0100 000s
|
|
{0xC0,0x00}, //110s
|
|
{0x50,0x00}, //0101 00s
|
|
{0x1E,0x00}, //0001 1110s
|
|
{0x03,0xC0}, //0000 0011 11s
|
|
{0x04,0x20}, //0000 0100 001s
|
|
{0x05,0x00}, //0000 0101 0000s
|
|
{0xE0,0x00}, //1110s
|
|
{0x1D,0x00}, //0001 1101s
|
|
{0x03,0x80}, //0000 0011 10s
|
|
{0x05,0x10}, //0000 0101 0001s
|
|
{0x68,0x00}, //0110 1s
|
|
{0x11,0x80}, //0001 0001 1s
|
|
{0x03,0x40}, //0000 0011 01s
|
|
{0x60,0x00}, //0110 0s
|
|
{0x11,0x00}, //0001 0001 0s
|
|
{0x05,0x20}, //0000 0101 0010s
|
|
{0x58,0x00}, //0101 1s
|
|
{0x03,0x00}, //0000 0011 00s
|
|
{0x05,0x30}, //0000 0101 0011s
|
|
{0x4C,0x00}, //0100 11s
|
|
{0x02,0xC0}, //0000 0010 11s
|
|
{0x05,0x40}, //0000 0101 0100s
|
|
{0x48,0x00}, //0100 10s
|
|
{0x02,0x80}, //0000 0010 10s
|
|
{0x44,0x00}, //0100 01s
|
|
{0x02,0x40}, //0000 0010 01s
|
|
{0x40,0x00}, //0100 00s
|
|
{0x02,0x00}, //0000 0010 00s
|
|
{0x2C,0x00}, //0010 110s
|
|
{0x05,0x50}, //0000 0101 0101s
|
|
{0x2A,0x00}, //0010 101s
|
|
{0x28,0x00}, //0010 100s
|
|
{0x1C,0x00}, //0001 1100s
|
|
{0x1B,0x00}, //0001 1011s
|
|
{0x10,0x80}, //0001 0000 1s
|
|
{0x10,0x00}, //0001 0000 0s
|
|
{0x0F,0x80}, //0000 1111 1s
|
|
{0x0F,0x00}, //0000 1111 0s
|
|
{0x0E,0x80}, //0000 1110 1s
|
|
{0x0E,0x00}, //0000 1110 0s
|
|
{0x0D,0x80}, //0000 1101 1s
|
|
{0x0D,0x00}, //0000 1101 0s
|
|
{0x04,0x40}, //0000 0100 010s
|
|
{0x04,0x60}, //0000 0100 011s
|
|
{0x05,0x60}, //0000 0101 0110s
|
|
{0x05,0x70}, //0000 0101 0111s
|
|
{0x70,0x00}, //0111s //last=1 ---------------------
|
|
{0x0C,0x80}, //0000 1100 1s
|
|
{0x00,0xA0}, //0000 0000 101s
|
|
{0x3C,0x00}, //0011 11s
|
|
{0x00,0x80}, //0000 0000 100s
|
|
{0x38,0x00}, //0011 10s
|
|
{0x34,0x00}, //0011 01s
|
|
{0x30,0x00}, //0011 00s
|
|
{0x26,0x00}, //0010 011s
|
|
{0x24,0x00}, //0010 010s
|
|
{0x22,0x00}, //0010 001s
|
|
{0x20,0x00}, //0010 000s
|
|
{0x1A,0x00}, //0001 1010s
|
|
{0x19,0x00}, //0001 1001s
|
|
{0x18,0x00}, //0001 1000s
|
|
{0x17,0x00}, //0001 0111s
|
|
{0x16,0x00}, //0001 0110s
|
|
{0x15,0x00}, //0001 0101s
|
|
{0x14,0x00}, //0001 0100s
|
|
{0x13,0x00}, //0001 0011s
|
|
{0x0C,0x00}, //0000 1100 0s
|
|
{0x0B,0x80}, //0000 1011 1s
|
|
{0x0B,0x00}, //0000 1011 0s
|
|
{0x0A,0x80}, //0000 1010 1s
|
|
{0x0A,0x00}, //0000 1010 0s
|
|
{0x09,0x80}, //0000 1001 1s
|
|
{0x09,0x00}, //0000 1001 0s
|
|
{0x08,0x80}, //0000 1000 1s
|
|
{0x01,0xC0}, //0000 0001 11s
|
|
{0x01,0x80}, //0000 0001 10s
|
|
{0x01,0x40}, //0000 0001 01s
|
|
{0x01,0x00}, //0000 0001 00s
|
|
{0x04,0x80}, //0000 0100 100s
|
|
{0x04,0xA0}, //0000 0100 101s
|
|
{0x04,0xC0}, //0000 0100 110s
|
|
{0x04,0xE0}, //0000 0100 111s
|
|
{0x05,0x80}, //0000 0101 1000s
|
|
{0x05,0x90}, //0000 0101 1001s
|
|
{0x05,0xA0}, //0000 0101 1010s
|
|
{0x05,0xB0}, //0000 0101 1011s
|
|
{0x05,0xC0}, //0000 0101 1100s
|
|
{0x05,0xD0}, //0000 0101 1101s
|
|
{0x05,0xE0}, //0000 0101 1110s
|
|
{0x05,0xF0}, //0000 0101 1111s
|
|
{0x06,0x00}}; //0000 011 (escape)
|
|
|
|
static const WebRtc_UWord8 TCOEF_MASK[103][2] = {{0xC0,0x00}, //10s
|
|
{0xF0,0x00}, //1111s
|
|
{0xFC,0x00}, //0101 01s
|
|
{0xFE,0x00}, //0010 111s
|
|
{0xFF,0x00}, //0001 1111s
|
|
{0xFF,0x80}, //0001 0010 1s
|
|
{0xFF,0x80}, //0001 0010 0s
|
|
{0xFF,0xC0}, //0000 1000 01s
|
|
{0xFF,0xC0}, //0000 1000 00s
|
|
{0xFF,0xE0}, //0000 0000 111s
|
|
{0xFF,0xE0}, //0000 0000 110s
|
|
{0xFF,0xE0}, //0000 0100 000s
|
|
{0xE0,0x00}, //110s
|
|
{0xFC,0x00}, //0101 00s
|
|
{0xFF,0x00}, //0001 1110s
|
|
{0xFF,0xC0}, //0000 0011 11s
|
|
{0xFF,0xE0}, //0000 0100 001s
|
|
{0xFF,0xF0}, //0000 0101 0000s
|
|
{0xF0,0x00}, //1110s
|
|
{0xFF,0x00}, //0001 1101s
|
|
{0xFF,0xC0}, //0000 0011 10s
|
|
{0xFF,0xF0}, //0000 0101 0001s
|
|
{0xF8,0x00}, //0110 1s
|
|
{0xFF,0x80}, //0001 0001 1s
|
|
{0xFF,0xC0}, //0000 0011 01s
|
|
{0xF8,0x00}, //0110 0s
|
|
{0xFF,0x80}, //0001 0001 0s
|
|
{0xFF,0xF0}, //0000 0101 0010s
|
|
{0xF8,0x00}, //0101 1s
|
|
{0xFF,0xC0}, //0000 0011 00s
|
|
{0xFF,0xF0}, //0000 0101 0011s
|
|
{0xFC,0x00}, //0100 11s
|
|
{0xFF,0xC0}, //0000 0010 11s
|
|
{0xFF,0xF0}, //0000 0101 0100s
|
|
{0xFC,0x00}, //0100 10s
|
|
{0xFF,0xC0}, //0000 0010 10s
|
|
{0xFC,0x00}, //0100 01s
|
|
{0xFF,0xC0}, //0000 0010 01s
|
|
{0xFC,0x00}, //0100 00s
|
|
{0xFF,0xC0}, //0000 0010 00s
|
|
{0xFE,0x00}, //0010 110s
|
|
{0xFF,0xF0}, //0000 0101 0101s
|
|
{0xFE,0x00}, //0010 101s
|
|
{0xFE,0x00}, //0010 100s
|
|
{0xFF,0x00}, //0001 1100s
|
|
{0xFF,0x00}, //0001 1011s
|
|
{0xFF,0x80}, //0001 0000 1s
|
|
{0xFF,0x80}, //0001 0000 0s
|
|
{0xFF,0x80}, //0000 1111 1s
|
|
{0xFF,0x80}, //0000 1111 0s
|
|
{0xFF,0x80}, //0000 1110 1s
|
|
{0xFF,0x80}, //0000 1110 0s
|
|
{0xFF,0x80}, //0000 1101 1s
|
|
{0xFF,0x80}, //0000 1101 0s
|
|
{0xFF,0xE0}, //0000 0100 010s
|
|
{0xFF,0xE0}, //0000 0100 011s
|
|
{0xFF,0xF0}, //0000 0101 0110s
|
|
{0xFF,0xF0}, //0000 0101 0111s
|
|
{0xF0,0x00}, //0111s //last=1 ----
|
|
{0xFF,0x80}, //0000 1100 1s
|
|
{0xFF,0xE0}, //0000 0000 101s
|
|
{0xFC,0x00}, //0011 11s
|
|
{0xFF,0xE0}, //0000 0000 100s
|
|
{0xFC,0x00}, //0011 10s
|
|
{0xFC,0x00}, //0011 01s
|
|
{0xFC,0x00}, //0011 00s
|
|
{0xFE,0x00}, //0010 011s
|
|
{0xFE,0x00}, //0010 010s
|
|
{0xFE,0x00}, //0010 001s
|
|
{0xFE,0x00}, //0010 000s
|
|
{0xFF,0x00}, //0001 1010s
|
|
{0xFF,0x00}, //0001 1001s
|
|
{0xFF,0x00}, //0001 1000s
|
|
{0xFF,0x00}, //0001 0111s
|
|
{0xFF,0x00}, //0001 0110s
|
|
{0xFF,0x00}, //0001 0101s
|
|
{0xFF,0x00}, //0001 0100s
|
|
{0xFF,0x00}, //0001 0011s
|
|
{0xFF,0x80}, //0000 1100 0s
|
|
{0xFF,0x80}, //0000 1011 1s
|
|
{0xFF,0x80}, //0000 1011 0s
|
|
{0xFF,0x80}, //0000 1010 1s
|
|
{0xFF,0x80}, //0000 1010 0s
|
|
{0xFF,0x80}, //0000 1001 1s
|
|
{0xFF,0x80}, //0000 1001 0s
|
|
{0xFF,0x80}, //0000 1000 1s
|
|
{0xFF,0xC0}, //0000 0001 11s
|
|
{0xFF,0xC0}, //0000 0001 10s
|
|
{0xFF,0xC0}, //0000 0001 01s
|
|
{0xFF,0xC0}, //0000 0001 00s
|
|
{0xFF,0xE0}, //0000 0100 100s
|
|
{0xFF,0xE0}, //0000 0100 101s
|
|
{0xFF,0xE0}, //0000 0100 110s
|
|
{0xFF,0xE0}, //0000 0100 111s
|
|
{0xFF,0xF0}, //0000 0101 1000s
|
|
{0xFF,0xF0}, //0000 0101 1001s
|
|
{0xFF,0xF0}, //0000 0101 1010s
|
|
{0xFF,0xF0}, //0000 0101 1011s
|
|
{0xFF,0xF0}, //0000 0101 1100s
|
|
{0xFF,0xF0}, //0000 0101 1101s
|
|
{0xFF,0xF0}, //0000 0101 1110s
|
|
{0xFF,0xF0}, //0000 0101 1111s
|
|
{0xFE,0x00}}; //0000 011 (escape)
|
|
|
|
static const WebRtc_Word32 TCOEF_SIZE[103] = { 3, 5, 7, 8, 9,10,10,11,11,12,12,12, 4, 7, 9,11,12,13, 5, 9,
|
|
11,13, 6,10,11, 6,10,13, 6,11,13, 7,11,13, 7,11, 7,11, 7,11,
|
|
8,13, 8, 8, 9, 9,10,10,10,10,10,10,10,10,12,12,13,13, 5,10,
|
|
12, 7,12, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,10,10,
|
|
10,10,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,13,13,
|
|
13,13, 8};
|
|
|
|
static const char TCOEF_LAST[103] = {0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,1,
|
|
1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,
|
|
1,1,1,1,1,1,1,1,1,1, 1,1,0};
|
|
|
|
// --------------------------------------
|
|
// --------------------------------------
|
|
// --------------------------------------
|
|
|
|
WebRtc_Word32
|
|
H263Info::CalculateMBOffset(const WebRtc_UWord8 numOfGOB) const
|
|
{
|
|
// calculate the number of MBs before this GOB
|
|
|
|
// sanity
|
|
if( numOfGOBs < numOfGOB)
|
|
{
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
WebRtc_Word32 numMBs = 0;
|
|
for(WebRtc_UWord8 GOB = 0; GOB< numOfGOB; GOB++)
|
|
{
|
|
numMBs += ptrNumOfMBs[GOB];
|
|
}
|
|
return numMBs;
|
|
}
|
|
|
|
|
|
H263Information::H263Information()
|
|
{
|
|
}
|
|
|
|
H263Information::~H263Information()
|
|
{
|
|
_infoMB.bufferSize = 0;
|
|
if (_infoMB.ptrBuffer)
|
|
{
|
|
delete [] _infoMB.ptrBuffer;
|
|
delete [] _infoMB.ptrBufferHMV;
|
|
delete [] _infoMB.ptrBufferVMV;
|
|
_infoMB.ptrBuffer = 0;
|
|
_infoMB.ptrBufferHMV = 0;
|
|
_infoMB.ptrBufferVMV = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
H263Information::Reset()
|
|
{
|
|
_info.uiH263PTypeFmt = 0;
|
|
_info.codecBits = 0;
|
|
_info.pQuant = 0;
|
|
_info.numOfGOBs = 0;
|
|
_info.cpmBit = 0;
|
|
_info.fType = 0;
|
|
|
|
memset(_info.ptrGOBbuffer, 0, sizeof(_info.ptrGOBbuffer));
|
|
memset(_info.ptrGOBbufferSBit, 0, sizeof(_info.ptrGOBbufferSBit));
|
|
memset(_info.ptrGQuant, 0, sizeof(_info.ptrGQuant));
|
|
memset(_info.ptrNumOfMBs, 0, sizeof(_info.ptrNumOfMBs));
|
|
memset(_info.ptrGroupNum, 0, sizeof(_info.ptrGroupNum));
|
|
|
|
if (_infoMB.ptrBuffer)
|
|
{
|
|
memset(_infoMB.ptrBuffer, 0, sizeof(WebRtc_UWord32) * _infoMB.bufferSize);
|
|
memset(_infoMB.ptrBufferHMV, 0, sizeof(WebRtc_UWord8) * _infoMB.bufferSize);
|
|
memset(_infoMB.ptrBufferVMV, 0, sizeof(WebRtc_UWord8) * _infoMB.bufferSize);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* WebRtc_Word32 GetInfo(const WebRtc_UWord8* ptrEncodedBuffer,
|
|
* const WebRtc_UWord32 length,
|
|
* const H263Info*& ptrInfo);
|
|
*
|
|
* Gets information from an encoded stream.
|
|
*
|
|
* Input:
|
|
* - ptrEncodedBuffer : Pointer to encoded stream.
|
|
* - length : Length in bytes of encoded stream.
|
|
*
|
|
* Output:
|
|
* - ptrInfo : Pointer to struct with H263 info.
|
|
*
|
|
* Return value:
|
|
* - 0 : ok
|
|
* - (-1) : Error
|
|
*/
|
|
WebRtc_Word32
|
|
H263Information::GetInfo(const WebRtc_UWord8* ptrEncodedBuffer,
|
|
const WebRtc_UWord32 length,
|
|
const H263Info*& ptrInfo)
|
|
{
|
|
if (!ptrEncodedBuffer || length < 8)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (!HasInfo(length))
|
|
{
|
|
if (-1 == FindInfo(ptrEncodedBuffer, length))
|
|
{
|
|
Reset();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ptrInfo = &_info;
|
|
return 0;
|
|
}
|
|
|
|
RtpVideoCodecTypes
|
|
H263Information::Type()
|
|
{
|
|
return kRtpH263Video;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* WebRtc_Word32 GetMBInfo(const WebRtc_UWord8* ptrEncodedBuffer,
|
|
* const WebRtc_UWord32 length,
|
|
* WebRtc_Word32 numOfGOB,
|
|
* const H263MBInfo*& ptrInfoMB);
|
|
*
|
|
* Gets macroblock positions for a GOB.
|
|
* Also, the horizontal and vertical motion vector for each MB are returned.
|
|
*
|
|
* Input:
|
|
* - ptrEncodedBuffer : Pointer to encoded stream.
|
|
* - length : Length in bytes of encoded stream.
|
|
* - numOfGOB : Group number of current GOB.
|
|
*
|
|
* Output:
|
|
* - infoMB : Pointer to struct with MB positions in bits for a GOB.
|
|
* Horizontal and vertical motion vector for each MB.
|
|
*
|
|
* Return value:
|
|
* - 0 : ok
|
|
* - (-1) : Error
|
|
*/
|
|
WebRtc_Word32
|
|
H263Information::GetMBInfo(const WebRtc_UWord8* ptrEncodedBuffer,
|
|
const WebRtc_UWord32 length,
|
|
const WebRtc_UWord8 numOfGOB,
|
|
const H263MBInfo*& ptrInfoMB)
|
|
{
|
|
if (!ptrEncodedBuffer || numOfGOB > _info.numOfGOBs - 1)
|
|
{
|
|
return -1;
|
|
}
|
|
if (-1 == VerifyAndAllocateMB())
|
|
{
|
|
return -1;
|
|
}
|
|
if (length != _info.ptrGOBbuffer[_info.numOfGOBs])
|
|
{
|
|
return -1;
|
|
}
|
|
if (!HasMBInfo(numOfGOB))
|
|
{
|
|
if (-1 == FindMBs(ptrEncodedBuffer, numOfGOB, length))
|
|
{
|
|
Reset();
|
|
return -1;
|
|
}
|
|
}
|
|
ptrInfoMB = &_infoMB;
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
H263Information::HasInfo(const WebRtc_UWord32 length)
|
|
{
|
|
if (!_info.ptrGOBbuffer)
|
|
{
|
|
return false;
|
|
}
|
|
if (_info.ptrGOBbuffer[0] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// has info, make sure current length matches info length
|
|
if (length != _info.ptrGOBbuffer[_info.numOfGOBs - 1])
|
|
{
|
|
Reset();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindInfo(const WebRtc_UWord8* ptrEncodedBuffer,
|
|
const WebRtc_UWord32 length)
|
|
{
|
|
_ptrData = ptrEncodedBuffer;
|
|
|
|
if (!PictureStartCode())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Gets picture size
|
|
if (-1 == FindPTypeFMT())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
FindFType();
|
|
FindCodecBits();
|
|
FindPQUANT();
|
|
FindCPMbit();
|
|
|
|
if (-1 == FindGOBs(length))
|
|
{
|
|
return -1;
|
|
}
|
|
if (-1 == SetNumOfMBs())
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::SetNumOfMBs()
|
|
{
|
|
// Source format: 000 - forbidden
|
|
// 001 - SQCIF 1 GOB - one macroblock row
|
|
// 010 - QCIF 1 GOB - one macroblock row
|
|
// 011 - CIF 1 GOB - one macroblock row
|
|
// 100 - 4CIF 1 GOB - two macroblock rows
|
|
// 101 - 16CIF 1 GOB - four macroblock rows
|
|
// 110 - reserved
|
|
// 111 - extended PTYPE
|
|
|
|
WebRtc_UWord16 numOfMBsPerGOB = 0;
|
|
|
|
switch (_info.uiH263PTypeFmt)
|
|
{
|
|
case 1: // SQCIF
|
|
numOfMBsPerGOB = 8;
|
|
_info.totalNumOfMBs = 8 * 6; //128x96
|
|
break;
|
|
case 2: // QCIF
|
|
numOfMBsPerGOB = 11;
|
|
_info.totalNumOfMBs = 11 * 9;
|
|
break;
|
|
case 3: // CIF
|
|
numOfMBsPerGOB = 22;
|
|
_info.totalNumOfMBs = 22 * 18;
|
|
break;
|
|
case 4: // 4CIF
|
|
numOfMBsPerGOB = 88;
|
|
_info.totalNumOfMBs = 88 * 18;
|
|
break;
|
|
case 5: // 16CIF
|
|
numOfMBsPerGOB = 352;
|
|
_info.totalNumOfMBs = 352 * 18;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
// loop through all GOBs
|
|
WebRtc_UWord16 numberOfMBs = 0;
|
|
for(WebRtc_UWord8 GOB = 0; GOB < (_info.numOfGOBs -1); GOB++)
|
|
{
|
|
_info.ptrNumOfMBs[GOB] = numOfMBsPerGOB * (_info.ptrGroupNum[GOB+1] - _info.ptrGroupNum[GOB]);
|
|
numberOfMBs += _info.ptrNumOfMBs[GOB];
|
|
}
|
|
_info.ptrNumOfMBs[_info.numOfGOBs -1] = _info.totalNumOfMBs - numberOfMBs;
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
H263Information::PictureStartCode()
|
|
{
|
|
// Picture start code (PSC) (22 bits)
|
|
// ----0--------1-------2----
|
|
// |00000000|00000000|100000xx|
|
|
// --------------------------
|
|
|
|
if ( _ptrData[0] == 0 &&
|
|
_ptrData[1] == 0 &&
|
|
(_ptrData[2] & 0x80) &&
|
|
(_ptrData[2] & 0x7C) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindPTypeFMT()
|
|
{
|
|
// Type Information (PTYPE) (Variable Length)(8/13 bits)
|
|
// ----3--------4--------5---
|
|
// |xxxxxxPP|PPPPPPpp|pppxxxxx|
|
|
// --------------------------
|
|
|
|
// Source format (bits 6-8)
|
|
_info.uiH263PTypeFmt = (_ptrData[4] >> 2) & 0x07;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
H263Information::FindFType()
|
|
{
|
|
// Type Information (PTYPE) (13 bits, source format != 111, not extended PTYPE)
|
|
// ----3--------4--------5---
|
|
// |xxxxxxPP|PPPPPPPP|PPPxxxxx|
|
|
// --------------------------
|
|
|
|
// Picture coding type (bit 9)
|
|
_info.fType = (_ptrData[4] & 0x02) >> 1; // 0 = I-frame, 1 = P-frame
|
|
}
|
|
|
|
void
|
|
H263Information::FindCodecBits()
|
|
{
|
|
// Type Information (PTYPE) (13 bits)
|
|
// ----3--------4--------5---
|
|
// |xxxxxxPP|PPPPPPPP|PPPxxxxx|
|
|
// --------------------------
|
|
|
|
// Bits 9-12 // bit 10: Unrestricted Motion Vector mode (annex D) 0-off, 1-on
|
|
_info.codecBits = (_ptrData[4] & 0x03) << 2; // bit 11: Syntax-based Arithmetic Coding mode (annex E)
|
|
_info.codecBits += (_ptrData[5] & 0xC0) >> 6; // bit 12: Advanced Prediction mode (annex F)
|
|
}
|
|
|
|
void
|
|
H263Information::FindPQUANT()
|
|
{
|
|
// Quantizer Information (PQUANT) (5 bits)
|
|
// ----5---
|
|
// |xxxQQQQQ|
|
|
// --------
|
|
|
|
_info.pQuant = _ptrData[5] & 0x1F;
|
|
}
|
|
|
|
void
|
|
H263Information::FindCPMbit()
|
|
{
|
|
// Continuous presence multipoWebRtc_Word32 and Video multiplex (CPM) (1 bit)
|
|
// ----6---
|
|
// |Cxxxxxxx|
|
|
// --------
|
|
|
|
_info.cpmBit = IsBitOne(48); // 0-off, 1-on
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindGOBs(const WebRtc_UWord32 length)
|
|
{
|
|
// Group of block layer (GOB).
|
|
// GOB header followed by data for (one or more rows) of macroblocks.
|
|
|
|
// Stuffing (GSTUF) (Variable length) consisting of less than 8 zero-bits. May be
|
|
// inserted by encoders so that the start of the GBSC is byte aligned.
|
|
// Group of block start code (GBSC) (17 bits). May be byte aligned.
|
|
// Group Number (GN) (5 bits). Group numbers 1-17 used for standard picture formats.
|
|
// 0 used in PSC.
|
|
// --------------------------------
|
|
// |GSTUF|00000000|00000000|1GGGGGxx|
|
|
// --------------------------------
|
|
|
|
WebRtc_UWord8 numOfGOB = 0;
|
|
WebRtc_UWord8 groupNum = 0;
|
|
WebRtc_UWord8 sBit = 0;
|
|
|
|
_info.ptrGroupNum[numOfGOB] = 0;
|
|
_info.ptrGOBbuffer[numOfGOB] = 0;
|
|
_info.ptrGOBbufferSBit[numOfGOB] = 0;
|
|
numOfGOB++;
|
|
|
|
for (WebRtc_UWord32 i = 3; (i < length - 2); i++)
|
|
{
|
|
if (_ptrData[i] == 0)
|
|
{
|
|
if (_ptrData[i + 1] == 0)
|
|
{
|
|
if (_ptrData[i + 2] & 0x80)
|
|
{
|
|
// GBSC byte aligned
|
|
groupNum = (_ptrData[i + 2] >> 2) & 0x1f;
|
|
_info.ptrGroupNum[numOfGOB] = groupNum;
|
|
_info.ptrGOBbuffer[numOfGOB] = i;
|
|
_info.ptrGOBbufferSBit[numOfGOB] = 0;
|
|
numOfGOB++;
|
|
}
|
|
}else
|
|
{
|
|
// check for non byte aligned GBSC
|
|
if ((_ptrData[i - 1] & 0x7F) == 0 && (_ptrData[i + 1] & 0xC0) == 0x40)
|
|
{
|
|
// |x0000000|00000000|01GGGGGx|
|
|
sBit = 1;
|
|
groupNum = (_ptrData[i + 1] >> 1) & 0x1f;
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x3F) == 0 && (_ptrData[i + 1] & 0xE0) == 0x20)
|
|
{
|
|
// |xx000000|00000000|001GGGGG|
|
|
sBit = 2;
|
|
groupNum = (_ptrData[i + 1]) & 0x1f;
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x1F) == 0 && (_ptrData[i + 1] & 0xF0) == 0x10)
|
|
{
|
|
// |xxx00000|00000000|0001GGGG|G
|
|
sBit = 3;
|
|
groupNum = ((_ptrData[i + 1] & 0x0F) << 1) | ((_ptrData[i + 2] >> 7) & 0x01);
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x0F) == 0 && (_ptrData[i + 1] & 0xF8) == 0x08)
|
|
{
|
|
// |xxxx0000|00000000|00001GGG|GG
|
|
sBit = 4;
|
|
groupNum = ((_ptrData[i + 1] & 0x07) << 2) | ((_ptrData[i + 2] >> 6) & 0x03);
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x07) == 0 && (_ptrData[i + 1] & 0xFC) == 0x04)
|
|
{
|
|
// |xxxxx000|00000000|000001GG|GGG
|
|
sBit = 5;
|
|
groupNum = ((_ptrData[i + 1] & 0x03) << 3) | ((_ptrData[i + 2] >> 5) & 0x07);
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x03) == 0 && (_ptrData[i + 1] & 0xFE) == 0x02)
|
|
{
|
|
// |xxxxxx00|00000000|0000001G|GGGG
|
|
sBit = 6;
|
|
groupNum = ((_ptrData[i + 1] & 0x01) << 4) | ((_ptrData[i + 2] >> 4) & 0x0F);
|
|
}
|
|
else if ((_ptrData[i - 1] & 0x01) == 0 && _ptrData[i + 1] == 0x01)
|
|
{
|
|
// |xxxxxxx0|00000000|00000001|GGGGG
|
|
sBit = 7;
|
|
groupNum = (_ptrData[i + 2] >> 3) & 0x1f;
|
|
}
|
|
else
|
|
{
|
|
sBit = 0;
|
|
groupNum = 0;
|
|
}
|
|
if (sBit)
|
|
{
|
|
_info.ptrGroupNum[numOfGOB] = groupNum;
|
|
_info.ptrGOBbuffer[numOfGOB] = i - 1;
|
|
_info.ptrGOBbufferSBit[numOfGOB] = sBit;
|
|
numOfGOB++;
|
|
}
|
|
}
|
|
if(numOfGOB >= MAX_NUMBER_OF_H263_GOB)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
_info.numOfGOBs = numOfGOB;
|
|
_info.ptrGOBbuffer[numOfGOB] = length;
|
|
_info.ptrGOBbufferSBit[numOfGOB] = 0;
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::VerifyAndAllocateMB()
|
|
{
|
|
WebRtc_UWord32 minimumSize = _info.totalNumOfMBs;
|
|
if (minimumSize == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (minimumSize > _infoMB.bufferSize)
|
|
{
|
|
// make sure that our buffer is big enough
|
|
if (_infoMB.ptrBuffer)
|
|
{
|
|
delete [] _infoMB.ptrBuffer;
|
|
delete [] _infoMB.ptrBufferHMV;
|
|
delete [] _infoMB.ptrBufferVMV;
|
|
}
|
|
_infoMB.ptrBuffer = new WebRtc_UWord32[minimumSize];
|
|
_infoMB.ptrBufferHMV = new WebRtc_UWord8[minimumSize];
|
|
_infoMB.ptrBufferVMV = new WebRtc_UWord8[minimumSize];
|
|
_infoMB.bufferSize = minimumSize;
|
|
|
|
// reset memory
|
|
memset(_infoMB.ptrBuffer, 0, sizeof(WebRtc_UWord32) * _infoMB.bufferSize);
|
|
memset(_infoMB.ptrBufferHMV, 0, sizeof(WebRtc_UWord8) * _infoMB.bufferSize);
|
|
memset(_infoMB.ptrBufferVMV, 0, sizeof(WebRtc_UWord8) * _infoMB.bufferSize);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
H263Information::HasMBInfo(const WebRtc_UWord8 numOfGOB)
|
|
{
|
|
if (!_infoMB.ptrBuffer)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
WebRtc_Word32 offset = _info.CalculateMBOffset(numOfGOB);
|
|
|
|
if (_infoMB.ptrBuffer[offset] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindMBs(const WebRtc_UWord8 *ptrEncodedBuffer,
|
|
const WebRtc_UWord8 numOfGOB,
|
|
const WebRtc_UWord32 length)
|
|
{
|
|
_bitCnt = 0;
|
|
WebRtc_Word32 bitCntOffset = 0;
|
|
_ptrData = ptrEncodedBuffer;
|
|
WebRtc_UWord32 payloadBytesToSend = length;
|
|
|
|
if (numOfGOB > 0)
|
|
{
|
|
// Point at current GOB
|
|
_ptrData += _info.ptrGOBbuffer[numOfGOB ];
|
|
payloadBytesToSend -= _info.ptrGOBbuffer[numOfGOB];
|
|
// Start bits to ignore
|
|
_bitCnt += _info.ptrGOBbufferSBit[numOfGOB];
|
|
// Byte with start bits has already been sent, start counting from next byte
|
|
if (_info.ptrGOBbufferSBit[numOfGOB])
|
|
{
|
|
bitCntOffset = 8;
|
|
}
|
|
}
|
|
|
|
WebRtc_Word32 offset = _info.CalculateMBOffset(numOfGOB);
|
|
WebRtc_UWord32 *sizeOfMBs = &_infoMB.ptrBuffer[offset];
|
|
WebRtc_UWord8 *hmv1 = &_infoMB.ptrBufferHMV[offset];
|
|
WebRtc_UWord8 *vmv1 = &_infoMB.ptrBufferVMV[offset];
|
|
|
|
// Header data
|
|
if (numOfGOB == 0)
|
|
{
|
|
// Picture layer
|
|
// -----------------------
|
|
// | Picture header | GOBs | // For GOB number 0, empty GOB header
|
|
// -----------------------
|
|
|
|
_bitCnt = 49;
|
|
if (_info.cpmBit)
|
|
{
|
|
_bitCnt += 2;
|
|
}
|
|
|
|
WebRtc_Word32 peiBit = IsBitOne(_bitCnt);
|
|
_bitCnt++;
|
|
if (peiBit)
|
|
{
|
|
_bitCnt += 8;
|
|
peiBit = IsBitOne(_bitCnt);
|
|
_bitCnt++;
|
|
if (peiBit)
|
|
{
|
|
_bitCnt += 9;
|
|
}
|
|
}
|
|
}
|
|
else if (numOfGOB < _info.numOfGOBs)
|
|
{
|
|
// Group of block layer (GOB).
|
|
// Group of block start code (GBSC) (17 bits).
|
|
// Group Number (GN) (5 bits).
|
|
// GOB Sub-Stream Indicator (GSBI) (2 bits). Only present if CPM = 1.
|
|
// GOB Frame ID (GFID) (2 bits).
|
|
// Quantizer Information (GQUANT) (5 bits).
|
|
// ----------------------------------------------------
|
|
// | GBSC | GN | GSBI | GFID | GQUANT | Macroblock data |
|
|
// ----------------------------------------------------
|
|
|
|
_bitCnt += 24;
|
|
if (_info.cpmBit)
|
|
{
|
|
_bitCnt += 2;
|
|
}
|
|
|
|
FindGQUANT(numOfGOB);
|
|
|
|
_bitCnt += 5;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Start of macroblock data
|
|
// -----------------------
|
|
// | MB header | blockdata |
|
|
// -----------------------
|
|
for (WebRtc_Word32 j = 0; j < _info.ptrNumOfMBs[numOfGOB]; j++)
|
|
{
|
|
// MB header
|
|
// ------------------------------------------------
|
|
// | COD(inter) | MCBPC | CBPY | DQUANT |MVD(inter) |
|
|
// ------------------------------------------------
|
|
WebRtc_Word32 codBit = 0;
|
|
if (_info.fType)
|
|
{
|
|
codBit = IsBitOne(_bitCnt);
|
|
_bitCnt++;
|
|
}
|
|
|
|
if (codBit == 0) // if codBit == 1, no further info transmitted for this MB
|
|
{
|
|
WebRtc_Word32 mbType = 0;
|
|
char cbp[6];
|
|
|
|
// Get MB type & coded block pattern for chrominance (MCBPC)
|
|
WebRtc_Word32 size = FindMCBPC(mbType, cbp);
|
|
|
|
_bitCnt += size;
|
|
|
|
if (size == -1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Get coded block pattern for luminance (CBPY)
|
|
size = FindCBPY(mbType, cbp);
|
|
|
|
_bitCnt += size;
|
|
|
|
if (size == -1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Quantizer information (DQUANT), change in QUANT
|
|
if (mbType == 1 || mbType == 4)
|
|
{
|
|
_bitCnt += 2;
|
|
}
|
|
|
|
// Get motion vector data (MVD) (inter-frames)
|
|
if (_info.fType && (mbType < 3 || mbType == 5))
|
|
{
|
|
// Horizontal and vertical component
|
|
for (WebRtc_Word32 k = 0; k < 2; k++)
|
|
{
|
|
size = FindMVD(j, k, hmv1, vmv1);
|
|
|
|
_bitCnt += size;
|
|
|
|
if (size == -1)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Block data. 1MB = 6 blocks (4 luminance blocks + 2 color blocks)
|
|
// -----------------
|
|
// | intraDC | TCOEF |
|
|
// -----------------
|
|
WebRtc_Word32 numOfBlocks = 6;
|
|
|
|
WebRtc_Word32 WebRtc_Word32raDC = 0;
|
|
if (mbType == 3 || mbType == 4)
|
|
{
|
|
WebRtc_Word32raDC = 8;
|
|
}
|
|
|
|
for (WebRtc_Word32 i = 0; i < numOfBlocks; i++)
|
|
{
|
|
// Get WebRtc_Word32raDC coefficient
|
|
_bitCnt += WebRtc_Word32raDC;
|
|
|
|
// Get non-WebRtc_Word32RA dc coefficients
|
|
if (cbp[i]) // presence indicated by CBPY and CBPC
|
|
{
|
|
WebRtc_Word32 last = 0;
|
|
while (last == 0)
|
|
{
|
|
// Get transform coefficient (TCOEF)
|
|
size = FindTCOEF(last);
|
|
|
|
_bitCnt += size;
|
|
|
|
if (size == -1)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// end of MB
|
|
sizeOfMBs[j] = _bitCnt - bitCntOffset;
|
|
}
|
|
else
|
|
{
|
|
// end of MB
|
|
sizeOfMBs[j] = _bitCnt - bitCntOffset;
|
|
}
|
|
}
|
|
// end of MBs
|
|
WebRtc_Word32 nextByte = _bitCnt >> 3;
|
|
WebRtc_Word32 nextByteRem = _bitCnt % 8;
|
|
if (nextByteRem)
|
|
{
|
|
nextByte++;
|
|
}
|
|
|
|
// Check for next GOB/end of picture
|
|
if (numOfGOB < (_info.numOfGOBs - 1))
|
|
{
|
|
// Test with GSTUF, GBSC (0000 0000 0000 0000 1)
|
|
if (_ptrData[nextByte] == 0 &&
|
|
_ptrData[nextByte + 1] == 0 &&
|
|
_ptrData[nextByte + 2] & 0x80)
|
|
{
|
|
sizeOfMBs[_info.ptrNumOfMBs[numOfGOB] - 1] = (nextByte << 3) - bitCntOffset;
|
|
return 1; // ok, next GOB
|
|
}
|
|
// ...without GSTUF
|
|
if (IsGBSC())
|
|
{
|
|
return 1; // ok, next GOB
|
|
}
|
|
}
|
|
else if (numOfGOB == (_info.numOfGOBs - 1))
|
|
{
|
|
// Picture end code may be included, (PSTUF (optional), EOS (22bits), ESTUF)
|
|
if (((WebRtc_UWord32) nextByte == payloadBytesToSend) ||
|
|
((WebRtc_UWord32)(nextByte + 2) == payloadBytesToSend) ||
|
|
((WebRtc_UWord32)(nextByte + 3) == payloadBytesToSend))
|
|
{
|
|
sizeOfMBs[_info.ptrNumOfMBs[numOfGOB] - 1] = (payloadBytesToSend << 3) - bitCntOffset;
|
|
return 1; // ok, end of picture layer
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindMCBPC(WebRtc_Word32 &mbType, char *cbp)
|
|
{
|
|
if (_info.fType == 0) // intra frame
|
|
{
|
|
ByteAlignData(MCBPC_I_MAX_CODE_LENGTH);
|
|
|
|
WebRtc_Word32 i;
|
|
for (i = 0; i < MCBPC_I_TABLE_LENGTH - 1; i++)
|
|
{
|
|
if ((_dataShifted[0] & MCBPC_I_MASK[i][0]) == MCBPC_I_CODE[i][0])
|
|
{
|
|
cbp[4] = MCBPC_I_CBPC[i][0];
|
|
cbp[5] = MCBPC_I_CBPC[i][1];
|
|
mbType = MCBPC_I_MBTYPE[i];
|
|
|
|
return MCBPC_I_SIZE[i];
|
|
}
|
|
}
|
|
// last row
|
|
i = MCBPC_I_TABLE_LENGTH - 1;
|
|
if ((_dataShifted[0] & MCBPC_I_MASK[i][0]) == MCBPC_I_CODE[i][0] &&
|
|
(_dataShifted[1] & MCBPC_I_MASK[i][1]) == MCBPC_I_CODE[i][1])
|
|
{
|
|
cbp[4] = MCBPC_I_CBPC[i][0];
|
|
cbp[5] = MCBPC_I_CBPC[i][1];
|
|
mbType = MCBPC_I_MBTYPE[i];
|
|
|
|
return MCBPC_I_SIZE[i];
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
else // inter frame
|
|
{
|
|
ByteAlignData(MCBPC_P_MAX_CODE_LENGTH);
|
|
|
|
for (WebRtc_Word32 i = 0; i < MCBPC_P_TABLE_LENGTH; i++)
|
|
{
|
|
if ((_dataShifted[0] & MCBPC_P_MASK[i][0]) == MCBPC_P_CODE[i][0] &&
|
|
(_dataShifted[1] & MCBPC_P_MASK[i][1]) == MCBPC_P_CODE[i][1])
|
|
{
|
|
cbp[4] = MCBPC_P_CBPC[i][0];
|
|
cbp[5] = MCBPC_P_CBPC[i][1];
|
|
mbType = MCBPC_P_MBTYPE[i];
|
|
|
|
return MCBPC_P_SIZE[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindCBPY(WebRtc_Word32 mbType, char *cbp)
|
|
{
|
|
ByteAlignData(CBPY_MAX_CODE_LENGTH);
|
|
|
|
for (WebRtc_Word32 i = 0; i < CBPY_TABLE_LENGTH; i++)
|
|
{
|
|
if ((_dataShifted[0] & CBPY_MASK[i][0]) == CBPY_CODE[i][0])
|
|
{
|
|
cbp[0] = CBPY_CBPY[i][0];
|
|
cbp[1] = CBPY_CBPY[i][1];
|
|
cbp[2] = CBPY_CBPY[i][2];
|
|
cbp[3] = CBPY_CBPY[i][3];
|
|
|
|
if (mbType == 0 || mbType == 1)
|
|
{
|
|
for (WebRtc_Word32 k = 0; k < 4; k++)
|
|
{
|
|
if (cbp[k])
|
|
{
|
|
cbp[k] = 0;
|
|
}
|
|
else
|
|
{
|
|
cbp[k] = 1;
|
|
}
|
|
}
|
|
}
|
|
return CBPY_SIZE[i];
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindMVD(WebRtc_Word32 numOfMB, WebRtc_Word32 verORhor, WebRtc_UWord8 *hmv1, WebRtc_UWord8 *vmv1)
|
|
{
|
|
ByteAlignData(MVD_MAX_CODE_LENGTH);
|
|
|
|
for (WebRtc_Word32 i = 0; i < MVD_TABLE_LENGTH; i++)
|
|
{
|
|
if ((_dataShifted[0] & MVD_MASK[i][0]) == MVD_CODE[i][0] &&
|
|
(_dataShifted[1] & MVD_MASK[i][1]) == MVD_CODE[i][1])
|
|
{
|
|
// Store horizontal/vertical motion vector predictor (2's complement number)
|
|
WebRtc_Word32 index = i - 32;
|
|
if (index < 0)
|
|
{
|
|
index = ~ (-index-1);
|
|
}
|
|
|
|
if (verORhor == 0)
|
|
{
|
|
hmv1[numOfMB] = static_cast<WebRtc_UWord8>(index);
|
|
|
|
} else
|
|
{
|
|
vmv1[numOfMB] = static_cast<WebRtc_UWord8>(index);
|
|
}
|
|
|
|
return MVD_SIZE[i];
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
H263Information::FindTCOEF(WebRtc_Word32 &last)
|
|
{
|
|
ByteAlignData(TCOEF_MAX_CODE_LENGTH);
|
|
|
|
for (WebRtc_Word32 i = 0; i < TCOEF_TABLE_LENGTH; i++)
|
|
{
|
|
if ((_dataShifted[0] & TCOEF_MASK[i][0]) == TCOEF_CODE[i][0] &&
|
|
(_dataShifted[1] & TCOEF_MASK[i][1]) == TCOEF_CODE[i][1])
|
|
{
|
|
last = TCOEF_LAST[i];
|
|
if (i == (TCOEF_TABLE_LENGTH - 1))
|
|
{
|
|
if (IsBitOne(_bitCnt + 7))
|
|
{
|
|
last = 1;
|
|
}
|
|
return 22;
|
|
}
|
|
return TCOEF_SIZE[i];
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool
|
|
H263Information::IsGBSC()
|
|
{
|
|
// Group of block layer (GOB).
|
|
// Stuffing (GSTUF) (Variable length) consisting of less than 8 zero-bits. May be
|
|
// inserted by encoders so that the start of the GBSC is byte aligned.
|
|
// Group of block start code (GBSC) (17 bits). May be byte aligned.
|
|
// Group Number (GN) (5 bits). Group numbers 1-17 used for standard picture formats.
|
|
// --------------------------------
|
|
// |GSTUF|00000000|00000000|1GGGGGxx|
|
|
// --------------------------------
|
|
|
|
ByteAlignData(3);
|
|
|
|
if (_dataShifted[0] == 0 && _dataShifted[1] == 0 && (_dataShifted[2] & 0x80) == 0x80)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
H263Information::FindGQUANT(WebRtc_Word32 numOfGOB)
|
|
{
|
|
ByteAlignData(1);
|
|
|
|
_info.ptrGQuant[numOfGOB] = (_dataShifted[0] >> 3) & 0x1F;
|
|
}
|
|
|
|
WebRtc_UWord8
|
|
H263Information::IsBitOne(const WebRtc_Word32 bitCnt) const
|
|
{
|
|
WebRtc_Word32 curByte = bitCnt >> 3;
|
|
WebRtc_Word32 bit = bitCnt % 8;
|
|
|
|
switch(bit)
|
|
{
|
|
case 0:
|
|
return _ptrData[curByte] & 0x80;
|
|
case 1:
|
|
return _ptrData[curByte] & 0x40;
|
|
case 2:
|
|
return _ptrData[curByte] & 0x20;
|
|
case 3:
|
|
return _ptrData[curByte] & 0x10;
|
|
case 4:
|
|
return _ptrData[curByte] & 0x08;
|
|
case 5:
|
|
return _ptrData[curByte] & 0x04;
|
|
case 6:
|
|
return _ptrData[curByte] & 0x02;
|
|
case 7:
|
|
return _ptrData[curByte] & 0x01;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
H263Information::ByteAlignData(WebRtc_Word32 numOfBytes)
|
|
{
|
|
WebRtc_Word32 sByte = _bitCnt >> 3;
|
|
WebRtc_Word32 sBit = _bitCnt % 8;
|
|
|
|
// Shift to byte align
|
|
WebRtc_Word32 i = 0;
|
|
do
|
|
{
|
|
_dataShifted[i] = _ptrData[sByte] << sBit;
|
|
_dataShifted[i++] += _ptrData[++sByte] >> (8 - sBit);
|
|
} while (i < numOfBytes);
|
|
}
|
|
} // namespace webrtc
|