You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

477 lines
11 KiB

/*
* H.265 video codec.
* Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
*
* This file is part of libde265.
*
* libde265 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libde265 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libde265. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libde265/cabac.h"
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void simple_getline(char** lineptr,size_t* linelen,FILE* fh)
{
const int LINESIZE=1000;
if (*lineptr==NULL) {
*linelen = LINESIZE;
*lineptr = (char*)malloc(LINESIZE);
}
char* p = *lineptr;
for (;;) {
assert(p - *lineptr < LINESIZE);
int c = fgetc(fh);
if (c == EOF || c == '\n') {
*p = 0;
break;
}
*p++ = c;
}
}
void generate_entropy_table()
{
#if 000
const int nSymbols=1000*1000*10;
const int oversample = 10;
double tab[64][2];
for (int i=0;i<64;i++)
for (int k=0;k<2;k++)
tab[i][k]=0;
srand(time(0));
//srand(123);
int cnt=1;
for (;;cnt++) {
printf("-------------------- %d --------------------\n",cnt);
for (int s=0;s<63;s++) {
CABAC_encoder_bitstream cabac_mix0;
CABAC_encoder_bitstream cabac_mix1;
CABAC_encoder_bitstream cabac_ref;
for (int i=0;i<nSymbols*oversample;i++) {
int r = rand();
int n = (r>>2) % 63;
int m = (r>>1) & 1;
int b = r & 1;
context_model model;
model.MPSbit = 1;
model.state = n;
cabac_ref.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
cabac_mix0.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
cabac_mix1.write_CABAC_bit(&model, b);
if (i%oversample == oversample/2) {
model.MPSbit = 1;
model.state = s;
cabac_mix0.write_CABAC_bit(&model, 0);
model.MPSbit = 1;
model.state = s;
cabac_mix1.write_CABAC_bit(&model, 1);
//b = rand() & 1;
//cabac_mix.write_CABAC_bypass(1);
}
}
cabac_ref.flush_CABAC();
cabac_mix0.flush_CABAC();
cabac_mix1.flush_CABAC();
int bits_ref = cabac_ref.size()*8;
int bits_mix0 = cabac_mix0.size()*8;
int bits_mix1 = cabac_mix1.size()*8;
//printf("bits: %d %d\n",bits_ref,bits_mix);
int bits_diff0 = bits_mix0-bits_ref;
int bits_diff1 = bits_mix1-bits_ref;
//printf("bits diff: %d\n",bits_diff);
double bits_per_symbol0 = bits_diff0 / double(nSymbols);
double bits_per_symbol1 = bits_diff1 / double(nSymbols);
tab[s][0] += bits_per_symbol0;
tab[s][1] += bits_per_symbol1;
double bps0 = tab[s][0]/cnt;
double bps1 = tab[s][1]/cnt;
printf("/* state=%2d */ 0x%05x /* %f */, 0x%05x /* %f */,\n", s,
(int)(bps1*0x8000), bps1,
(int)(bps0*0x8000), bps0);
}
printf(" 0x0010c, 0x3bfbb /* dummy, should never be used */\n");
}
#endif
}
int probTab[128+2] = {
1537234,1602970,
1608644,1815493,
1822246,2245961,
916773,1329391,
1337504,1930659,
1063692,1707588,
868294,1532108,
842934,1555538,
689043,1396941,
860184,1789964,
534165,1258482,
672508,1598821,
578782,1476240,
602247,1613140,
409393,1206638,
459294,1356779,
430124,1359893,
308326,1050647,
313100,1099956,
293887,1088978,
220901,869582,
214967,881695,
197226,856990,
166131,767761,
152514,737406,
128332,663998,
117638,632653,
106178,595539,
90898,539506,
83437,509231,
76511,492801,
64915,443096,
57847,409809,
52730,385395,
45707,354059,
42018,333028,
37086,308073,
33256,284497,
36130,299172,
28831,270716,
25365,244840,
22850,221896,
19732,201462,
17268,183729,
15252,168106,
13787,153979,
12187,141455,
10821,130337,
9896,120165,
8626,112273,
8162,103886,
7201,96441,
6413,89805,
5886,83733,
5447,78084,
4568,73356,
4388,68831,
3959,64688,
3750,60804,
3407,57271,
3109,54024,
2820,51099,
48569,1451987,
0, 0,
0*22686225, 0
};
void generate_entropy_table_probTableWeighted()
{
#if 000
int64_t probTabSum=0;
for (int i=0;i<130;i++)
probTabSum += probTab[i];
const int nSymbols=1000*1000*10;
const int oversample = 10;
double tab[64][2];
for (int i=0;i<64;i++)
for (int k=0;k<2;k++)
tab[i][k]=0;
srand(time(0));
//srand(123);
int cnt=1;
for (;;cnt++) {
printf("-------------------- %d --------------------\n",cnt);
for (int s=0;s<63;s++) {
CABAC_encoder_bitstream cabac_mix0;
CABAC_encoder_bitstream cabac_mix1;
CABAC_encoder_bitstream cabac_ref;
for (int i=0;i<nSymbols*oversample;i++) {
int r = rand();
r %= probTabSum;
int idx=0;
while (r>probTab[idx]) {
r-=probTab[idx];
idx++;
}
assert(idx<=128);
int n = idx/2;
int b = idx&1;
bool bypass = (idx==128);
printf("%d %d %d\n",n,b,bypass);
context_model model;
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_ref.write_CABAC_bypass(1);
else cabac_ref.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_mix0.write_CABAC_bypass(1);
else cabac_mix0.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_mix1.write_CABAC_bypass(1);
else cabac_mix1.write_CABAC_bit(&model, b);
if (i%oversample == oversample/2) {
model.MPSbit = 1;
model.state = s;
cabac_mix0.write_CABAC_bit(&model, 0);
model.MPSbit = 1;
model.state = s;
cabac_mix1.write_CABAC_bit(&model, 1);
//b = rand() & 1;
//cabac_mix.write_CABAC_bypass(1);
}
}
cabac_ref.flush_CABAC();
cabac_mix0.flush_CABAC();
cabac_mix1.flush_CABAC();
int bits_ref = cabac_ref.size()*8;
int bits_mix0 = cabac_mix0.size()*8;
int bits_mix1 = cabac_mix1.size()*8;
//printf("bits: %d %d\n",bits_ref,bits_mix);
int bits_diff0 = bits_mix0-bits_ref;
int bits_diff1 = bits_mix1-bits_ref;
//printf("bits diff: %d\n",bits_diff);
double bits_per_symbol0 = bits_diff0 / double(nSymbols);
double bits_per_symbol1 = bits_diff1 / double(nSymbols);
tab[s][0] += bits_per_symbol0;
tab[s][1] += bits_per_symbol1;
double bps0 = tab[s][0]/cnt;
double bps1 = tab[s][1]/cnt;
printf("/* state=%2d */ 0x%05x /* %f */, 0x%05x /* %f */,\n", s,
(int)(bps1*0x8000), bps1,
(int)(bps0*0x8000), bps0);
}
printf(" 0x0010c, 0x3bfbb /* dummy, should never be used */\n");
}
#endif
}
void generate_entropy_table_replay()
{
#if 000
const int oversample = 10;
char* lineptr = NULL;
size_t linelen = 0;
for (int s=0;s<63;s++) {
CABAC_encoder_bitstream cabac_mix0;
CABAC_encoder_bitstream cabac_mix1;
CABAC_encoder_bitstream cabac_ref;
int nSymbols = 0;
FILE* fh = fopen("streamdump-paris-intra","r");
for (int i=0;i<80000000;i++) {
simple_getline(&lineptr,&linelen,fh);
if (feof(fh))
break;
int n,b;
sscanf(lineptr,"%d %d",&n,&b);
bool bypass = (n==64);
if ((i%10000)==0)
{ printf("%d %d %d \r",i,n,b);
}
//printf("%d %d %d\n",n,b,bypass);
context_model model;
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_ref.write_CABAC_bypass(1);
else cabac_ref.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_mix0.write_CABAC_bypass(1);
else cabac_mix0.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_mix1.write_CABAC_bypass(1);
else cabac_mix1.write_CABAC_bit(&model, b);
if (i%oversample == oversample/2) {
model.MPSbit = 1;
model.state = s;
cabac_mix0.write_CABAC_bit(&model, 0);
model.MPSbit = 1;
model.state = s;
cabac_mix1.write_CABAC_bit(&model, 1);
nSymbols++;
//b = rand() & 1;
//cabac_mix.write_CABAC_bypass(1);
}
}
fclose(fh);
cabac_ref.flush_CABAC();
cabac_mix0.flush_CABAC();
cabac_mix1.flush_CABAC();
int bits_ref = cabac_ref.size()*8;
int bits_mix0 = cabac_mix0.size()*8;
int bits_mix1 = cabac_mix1.size()*8;
//printf("bits: %d %d\n",bits_ref,bits_mix);
int bits_diff0 = bits_mix0-bits_ref;
int bits_diff1 = bits_mix1-bits_ref;
//printf("bits diff: %d\n",bits_diff);
double bits_per_symbol0 = bits_diff0 / double(nSymbols);
double bits_per_symbol1 = bits_diff1 / double(nSymbols);
double bps0 = bits_per_symbol0;
double bps1 = bits_per_symbol1;
printf("/* state=%2d */ 0x%05x /* %f */, 0x%05x /* %f */,\n", s,
(int)(bps1*0x8000), bps1,
(int)(bps0*0x8000), bps0);
}
printf(" 0x0010c, 0x3bfbb /* dummy, should never be used */\n");
#endif
}
void test_entropy_table_replay()
{
#if 000
char* lineptr = NULL;
size_t linelen = 0;
CABAC_encoder_bitstream cabac_bs;
CABAC_encoder_estim cabac_estim;
//FILE* fh = fopen("y","r");
//FILE* fh = fopen("own-dump","r");
//FILE* fh = fopen("rawstream-dump","r");
//FILE* fh = fopen("johnny-stream-dump","r");
FILE* fh = fopen("streamdump-paris-intra","r");
for (int i=0;i<80000000;i++) {
simple_getline(&lineptr,&linelen,fh);
if (feof(fh))
break;
int n,b;
sscanf(lineptr,"%d %d",&n,&b);
b=!b;
bool bypass = (n==64);
if ((i%10000)==0)
{ printf("%d %d %d \n",i,n,b);
}
context_model model;
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_bs.write_CABAC_bypass(1);
else cabac_bs.write_CABAC_bit(&model, b);
model.MPSbit = 1;
model.state = n;
if (bypass) cabac_estim.write_CABAC_bypass(1);
else cabac_estim.write_CABAC_bit(&model, b);
}
fclose(fh);
printf("bs:%d estim:%d\n",cabac_bs.size(),cabac_estim.size());
#endif
}
int main(int argc, char** argv)
{
//generate_entropy_table();
//generate_entropy_table_replay();
test_entropy_table_replay();
return 0;
}