Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
web-ui-redesign
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gautam Chitnis
web-ui-redesign
Commits
9c11fac3
Commit
9c11fac3
authored
Apr 21, 2004
by
Christophe Massiot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* modules/stream_out/transrate: Rewrote the transrater to use a SAD error
estimation ; if the error is too high, lower the quantizer scale.
parent
a7bac1e6
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1546 additions
and
981 deletions
+1546
-981
modules/stream_out/transrate/Modules.am
modules/stream_out/transrate/Modules.am
+1
-1
modules/stream_out/transrate/block.c
modules/stream_out/transrate/block.c
+806
-0
modules/stream_out/transrate/frame.c
modules/stream_out/transrate/frame.c
+519
-942
modules/stream_out/transrate/getvlc.h
modules/stream_out/transrate/getvlc.h
+1
-0
modules/stream_out/transrate/putvlc.h
modules/stream_out/transrate/putvlc.h
+74
-2
modules/stream_out/transrate/transrate.c
modules/stream_out/transrate/transrate.c
+33
-30
modules/stream_out/transrate/transrate.h
modules/stream_out/transrate/transrate.h
+112
-6
No files found.
modules/stream_out/transrate/Modules.am
View file @
9c11fac3
SOURCES_stream_out_transrate = transrate.c frame.c getvlc.h putvlc.h
SOURCES_stream_out_transrate = transrate.c frame.c
block.c
getvlc.h putvlc.h
modules/stream_out/transrate/block.c
0 → 100644
View file @
9c11fac3
/*****************************************************************************
* block.c: MPEG2 video transrating module
*****************************************************************************
* Copyright (C) 2003-2004 VideoLAN
* Copyright (C) 2003 Antoine Missout
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
* $Id: frame.c,v 1.2 2004/03/03 11:39:06 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
* Antoine Missout
* Michel Lespinasse <walken@zoy.org>
* Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define NDEBUG 1
#include <assert.h>
#include <math.h>
#include <vlc/vlc.h>
#include <vlc/sout.h>
#include <vlc/input.h>
#include "transrate.h"
/****************************************************************************
* transrater, code from M2VRequantizer http://www.metakine.com/
****************************************************************************/
/////---- begin ext mpeg code
#include "getvlc.h"
#include "putvlc.h"
static
inline
int
saturate
(
int
i_value
)
{
if
(
i_value
>
2047
)
return
2047
;
if
(
i_value
<
-
2048
)
return
-
2048
;
return
i_value
;
}
static
int64_t
get_score
(
const
RunLevel
*
blk
,
RunLevel
*
new_blk
,
int
i_qscale
,
int
i_qscale_new
)
{
int64_t
score
=
0
;
int
i1
=
-
1
,
i2
=
-
1
;
while
(
new_blk
->
level
)
{
int
new_level
=
new_blk
->
level
;
int
level
=
blk
->
level
;
if
(
i1
>
64
||
i2
>
64
||
!
blk
->
run
||
!
new_blk
->
run
)
return
score
;
if
(
i1
+
blk
->
run
==
i2
+
new_blk
->
run
)
{
int64_t
tmp
=
saturate
(
level
*
i_qscale
)
-
saturate
(
new_level
*
i_qscale_new
);
i1
+=
blk
->
run
;
i2
+=
new_blk
->
run
;
score
+=
tmp
*
tmp
;
blk
++
;
new_blk
++
;
}
else
{
int64_t
tmp
=
saturate
(
level
*
i_qscale
);
i1
+=
blk
->
run
;
score
+=
tmp
*
tmp
;
blk
++
;
}
}
while
(
blk
->
level
)
{
int
level
=
blk
->
level
;
int64_t
tmp
=
saturate
(
level
*
i_qscale
);
i1
+=
blk
->
run
;
score
+=
tmp
*
tmp
;
blk
++
;
}
return
score
;
}
static
void
change_qscale
(
const
RunLevel
*
blk
,
RunLevel
*
new_blk
,
int
i_qscale
,
int
i_qscale_new
,
int
intra
)
{
int
i
=
0
,
li
=
0
;
int
rounding
;
if
(
intra
)
rounding
=
i_qscale_new
/
3
;
else
rounding
=
i_qscale_new
/
6
;
while
(
blk
->
level
)
{
int
level
=
blk
->
level
>
0
?
blk
->
level
:
-
blk
->
level
;
int
new_level
=
saturate
(
level
*
i_qscale
)
/
i_qscale_new
;
i
+=
blk
->
run
;
if
(
new_level
)
{
new_blk
->
run
=
i
-
li
;
new_blk
->
level
=
blk
->
level
>
0
?
new_level
:
-
new_level
;
new_blk
++
;
li
=
i
;
}
blk
++
;
}
new_blk
->
level
=
0
;
}
static
const
uint8_t
non_linear_mquant_table
[
32
]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
10
,
12
,
14
,
16
,
18
,
20
,
22
,
24
,
28
,
32
,
36
,
40
,
44
,
48
,
52
,
56
,
64
,
72
,
80
,
88
,
96
,
104
,
112
};
static
const
uint8_t
map_non_linear_mquant
[
113
]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
9
,
9
,
10
,
10
,
11
,
11
,
12
,
12
,
13
,
13
,
14
,
14
,
15
,
15
,
16
,
16
,
16
,
17
,
17
,
17
,
18
,
18
,
18
,
18
,
19
,
19
,
19
,
19
,
20
,
20
,
20
,
20
,
21
,
21
,
21
,
21
,
22
,
22
,
22
,
22
,
23
,
23
,
23
,
23
,
24
,
24
,
24
,
24
,
24
,
24
,
24
,
25
,
25
,
25
,
25
,
25
,
25
,
25
,
26
,
26
,
26
,
26
,
26
,
26
,
26
,
26
,
27
,
27
,
27
,
27
,
27
,
27
,
27
,
27
,
28
,
28
,
28
,
28
,
28
,
28
,
28
,
29
,
29
,
29
,
29
,
29
,
29
,
29
,
29
,
29
,
29
,
30
,
30
,
30
,
30
,
30
,
30
,
30
,
31
,
31
,
31
,
31
,
31
};
int
scale_quant
(
transrate_t
*
tr
,
double
qrate
)
{
int
i_quant
=
(
int
)
floor
(
tr
->
quantizer_scale
*
qrate
+
0
.
5
);
if
(
tr
->
q_scale_type
)
{
if
(
i_quant
<
1
)
i_quant
=
1
;
if
(
i_quant
>
112
)
i_quant
=
112
;
i_quant
=
non_linear_mquant_table
[
map_non_linear_mquant
[
i_quant
]];
}
else
{
if
(
i_quant
<
2
)
i_quant
=
2
;
if
(
i_quant
>
62
)
i_quant
=
62
;
i_quant
=
(
i_quant
/
2
)
*
2
;
// Must be *even*
}
return
i_quant
;
}
int
increment_quant
(
transrate_t
*
tr
,
int
i_quant
)
{
if
(
tr
->
q_scale_type
)
{
assert
(
i_quant
>=
1
&&
i_quant
<=
112
);
i_quant
=
map_non_linear_mquant
[
i_quant
]
+
1
;
if
(
i_quant
>
31
)
i_quant
=
31
;
i_quant
=
non_linear_mquant_table
[
i_quant
];
}
else
{
assert
(
!
(
i_quant
&
1
));
i_quant
+=
2
;
if
(
i_quant
>
62
)
i_quant
=
62
;
}
return
i_quant
;
}
static
int
decrement_quant
(
transrate_t
*
tr
,
int
i_quant
)
{
if
(
tr
->
q_scale_type
)
{
assert
(
i_quant
>=
1
&&
i_quant
<=
112
);
i_quant
=
map_non_linear_mquant
[
i_quant
]
-
1
;
if
(
i_quant
<
1
)
i_quant
=
1
;
i_quant
=
non_linear_mquant_table
[
i_quant
];
}
else
{
assert
(
!
(
i_quant
&
1
));
i_quant
-=
2
;
if
(
i_quant
<
2
)
i_quant
=
2
;
}
return
i_quant
;
}
static
void
quantize_block
(
transrate_t
*
tr
,
RunLevel
*
new_blk
,
int
intra
)
{
RunLevel
old_blk
[
65
];
RunLevel
*
blk
=
old_blk
;
const
uint8_t
*
old_matrix
,
*
new_matrix
;
int
i
=
0
,
li
=
0
;
memcpy
(
blk
,
new_blk
,
65
*
sizeof
(
RunLevel
)
);
if
(
intra
)
{
old_matrix
=
tr
->
intra_quantizer_matrix
;
new_matrix
=
mpeg4_default_intra_matrix
;
}
else
{
old_matrix
=
tr
->
non_intra_quantizer_matrix
;
new_matrix
=
mpeg4_default_non_intra_matrix
;
}
while
(
blk
->
level
)
{
int
level
=
blk
->
level
>
0
?
blk
->
level
:
-
blk
->
level
;
int
new_level
=
(
level
*
old_matrix
[
i
]
+
new_matrix
[
i
]
/
2
)
/
new_matrix
[
i
];
i
+=
blk
->
run
;
if
(
new_level
)
{
new_blk
->
run
=
i
-
li
;
new_blk
->
level
=
blk
->
level
>
0
?
new_level
:
-
new_level
;
new_blk
++
;
li
=
i
;
}
blk
++
;
}
new_blk
->
level
=
0
;
}
int
transrate_mb
(
transrate_t
*
tr
,
RunLevel
blk
[
6
][
65
],
RunLevel
new_blk
[
6
][
65
],
int
i_cbp
,
int
intra
)
{
int
i_qscale
=
tr
->
quantizer_scale
;
int
i_guessed_qscale
=
tr
->
new_quantizer_scale
;
int64_t
i_last_error
=
0
;
int
i_last_qscale
;
int
i_last_qscale_same_error
=
0
;
int
i_direction
=
0
;
int
i_new_cbp
;
int
i_nb_blocks
=
0
;
int
i_nb_coeffs
=
0
;
int
i
;
for
(
i
=
0
;
i
<
6
;
i
++
)
{
if
(
i_cbp
&
(
1
<<
(
5
-
i
))
)
{
RunLevel
*
cur_blk
=
blk
[
i
];
i_nb_blocks
++
;
while
(
cur_blk
->
level
)
{
cur_blk
++
;
i_nb_coeffs
++
;
}
}
}
/* See if we can change quantizer scale */
for
(
;
;
)
{
int64_t
i_error
=
0
;
i_new_cbp
=
0
;
for
(
i
=
0
;
i
<
6
;
i
++
)
{
if
(
i_cbp
&
(
1
<<
(
5
-
i
))
)
{
int64_t
i_block_error
;
change_qscale
(
blk
[
i
],
new_blk
[
i
],
i_qscale
,
i_guessed_qscale
,
intra
);
i_block_error
=
get_score
(
blk
[
i
],
new_blk
[
i
],
i_qscale
,
i_guessed_qscale
);
if
(
i
>
3
)
i_block_error
*=
4
;
if
(
i_block_error
>
i_error
)
i_error
=
i_block_error
;
if
(
new_blk
[
i
]
->
level
)
i_new_cbp
|=
(
1
<<
(
5
-
i
));
}
}
if
(
i_error
>=
(
int64_t
)
tr
->
i_minimum_error
&&
i_error
<=
(
int64_t
)
tr
->
i_admissible_error
)
{
break
;
}
if
(
i_nb_coeffs
<=
15
&&
i_error
<=
(
int64_t
)
tr
->
i_admissible_error
)
{
/* There is no interest in changing the qscale (takes up 5 bits
* we won't regain) */
break
;
}
if
(
!
i_direction
)
{
if
(
i_error
>
(
int64_t
)
tr
->
i_admissible_error
)
{
i_direction
=
-
1
;
i_last_qscale
=
i_guessed_qscale
;
i_guessed_qscale
=
decrement_quant
(
tr
,
i_guessed_qscale
);
}
else
{
i_direction
=
+
1
;
i_last_qscale
=
i_guessed_qscale
;
i_guessed_qscale
=
increment_quant
(
tr
,
i_guessed_qscale
);
i_last_error
=
i_error
;
i_last_qscale_same_error
=
i_last_qscale
;
}
if
(
i_guessed_qscale
==
i_last_qscale
)
break
;
}
else
if
(
i_direction
<
0
)
{
if
(
i_error
>
(
int64_t
)
tr
->
i_admissible_error
)
{
i_last_qscale
=
i_guessed_qscale
;
i_guessed_qscale
=
decrement_quant
(
tr
,
i_guessed_qscale
);
if
(
i_guessed_qscale
==
i_last_qscale
)
break
;
}
else
{
break
;
}
}
else
{
if
(
i_error
<
(
int64_t
)
tr
->
i_minimum_error
)
{
i_last_qscale
=
i_guessed_qscale
;
i_guessed_qscale
=
increment_quant
(
tr
,
i_guessed_qscale
);
if
(
i_error
>
i_last_error
)
{
i_last_error
=
i_error
;
i_last_qscale_same_error
=
i_last_qscale
;
}
if
(
i_guessed_qscale
==
i_last_qscale
)
{
if
(
i_last_error
==
i_error
)
{
i_guessed_qscale
=
i_last_qscale_same_error
;
if
(
i_guessed_qscale
==
i_qscale
)
{
memcpy
(
new_blk
,
blk
,
sizeof
(
RunLevel
)
*
65
*
6
);
i_new_cbp
=
i_cbp
;
}
else
{
i_new_cbp
=
0
;
for
(
i
=
0
;
i
<
6
;
i
++
)
{
if
(
i_cbp
&
(
1
<<
(
5
-
i
))
)
{
change_qscale
(
blk
[
i
],
new_blk
[
i
],
i_qscale
,
i_guessed_qscale
,
intra
);
if
(
new_blk
[
i
]
->
level
)
i_new_cbp
|=
(
1
<<
(
5
-
i
));
}
}
}
}
break
;
}
}
else
{
if
(
i_error
>
(
int64_t
)
tr
->
i_admissible_error
||
i_last_error
==
i_error
)
{
i_guessed_qscale
=
i_last_qscale_same_error
;
if
(
i_guessed_qscale
==
i_qscale
)
{
memcpy
(
new_blk
,
blk
,
sizeof
(
RunLevel
)
*
65
*
6
);
i_new_cbp
=
i_cbp
;
}
else
{
i_new_cbp
=
0
;
for
(
i
=
0
;
i
<
6
;
i
++
)
{
if
(
i_cbp
&
(
1
<<
(
5
-
i
))
)
{
change_qscale
(
blk
[
i
],
new_blk
[
i
],
i_qscale
,
i_guessed_qscale
,
intra
);
if
(
new_blk
[
i
]
->
level
)
i_new_cbp
|=
(
1
<<
(
5
-
i
));
}
}
}
}
break
;
}
}
}
tr
->
new_quantizer_scale
=
i_guessed_qscale
;
#if 0
/* Now see if we can drop coeffs */
for ( i = 0; i < 6; i++ )
{
if ( i_new_cbp & (1 << (5 - i)) )
{
for ( ; ; )
{
RunLevel *last_blk = new_blk[i];
uint8_t old_level;
while ( last_blk[1].level )
last_blk++;
if ( last_blk == new_blk[i] )
break;
old_level = last_blk->level;
last_blk->level = 0;
i_error = get_score( blk[i], new_blk[i],
i_qscale, i_guessed_qscale );
if ( i_error > tr->i_admissible_error )
{
last_blk->level = old_level;
break;
}
}
}
}
#endif
return
i_new_cbp
;
}
void
get_intra_block_B14
(
transrate_t
*
tr
,
RunLevel
*
blk
)
{
bs_transrate_t
*
bs
=
&
tr
->
bs
;
int
i
,
li
;
int
val
;
const
DCTtab
*
tab
;
li
=
i
=
0
;
for
(
;;
)
{
if
(
bs
->
i_bit_in_cache
>=
0x28000000
)
{
tab
=
DCT_B14AC_5
+
(
UBITS
(
bs
->
i_bit_in_cache
,
5
)
-
5
);
i
+=
tab
->
run
;
if
(
i
>=
64
)
break
;
/* end of block */
normal_code:
bs_flush
(
bs
,
tab
->
len
);
val
=
tab
->
level
;
val
=
(
val
^
SBITS
(
bs
->
i_bit_in_cache
,
1
))
-
SBITS
(
bs
->
i_bit_in_cache
,
1
);
blk
->
level
=
val
;
blk
->
run
=
i
-
li
-
1
;
li
=
i
;
blk
++
;
bs_flush
(
bs
,
1
);
continue
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x04000000
)
{
tab
=
DCT_B14_8
+
(
UBITS
(
bs
->
i_bit_in_cache
,
8
)
-
4
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
/* escape code */
i
+=
(
UBITS
(
bs
->
i_bit_in_cache
,
12
)
&
0x3F
)
-
64
;
if
(
i
>=
64
)
break
;
/* illegal, check needed to avoid buffer overflow */
bs_flush
(
bs
,
12
);
val
=
SBITS
(
bs
->
i_bit_in_cache
,
12
);
blk
->
level
=
val
;
blk
->
run
=
i
-
li
-
1
;
li
=
i
;
blk
++
;
bs_flush
(
bs
,
12
);
continue
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x02000000
)
{
tab
=
DCT_B14_10
+
(
UBITS
(
bs
->
i_bit_in_cache
,
10
)
-
8
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x00800000
)
{
tab
=
DCT_13
+
(
UBITS
(
bs
->
i_bit_in_cache
,
13
)
-
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x00200000
)
{
tab
=
DCT_15
+
(
UBITS
(
bs
->
i_bit_in_cache
,
15
)
-
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
{
tab
=
DCT_16
+
UBITS
(
bs
->
i_bit_in_cache
,
16
);
bs_flush
(
bs
,
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
fprintf
(
stderr
,
"Err in B14
\n
"
);
tr
->
b_error
=
1
;
break
;
/* illegal, check needed to avoid buffer overflow */
}
bs_flush
(
bs
,
2
);
/* dump end of block code */
blk
->
level
=
0
;
if
(
tr
->
mpeg4_matrix
)
quantize_block
(
tr
,
blk
,
1
);
}
void
get_intra_block_B15
(
transrate_t
*
tr
,
RunLevel
*
blk
)
{
bs_transrate_t
*
bs
=
&
tr
->
bs
;
int
i
,
li
;
int
val
;
const
DCTtab
*
tab
;
li
=
i
=
0
;
for
(
;;
)
{
if
(
bs
->
i_bit_in_cache
>=
0x04000000
)
{
tab
=
DCT_B15_8
+
(
UBITS
(
bs
->
i_bit_in_cache
,
8
)
-
4
);
i
+=
tab
->
run
;
if
(
i
<
64
)
{
normal_code:
bs_flush
(
bs
,
tab
->
len
);
val
=
tab
->
level
;
val
=
(
val
^
SBITS
(
bs
->
i_bit_in_cache
,
1
))
-
SBITS
(
bs
->
i_bit_in_cache
,
1
);
blk
->
level
=
val
;
blk
->
run
=
i
-
li
-
1
;
li
=
i
;
blk
++
;
bs_flush
(
bs
,
1
);
continue
;
}
else
{
i
+=
(
UBITS
(
bs
->
i_bit_in_cache
,
12
)
&
0x3F
)
-
64
;
if
(
i
>=
64
)
break
;
/* illegal, check against buffer overflow */
bs_flush
(
bs
,
12
);
val
=
SBITS
(
bs
->
i_bit_in_cache
,
12
);
blk
->
level
=
val
;
blk
->
run
=
i
-
li
-
1
;
li
=
i
;
blk
++
;
bs_flush
(
bs
,
12
);
continue
;
}
}
else
if
(
bs
->
i_bit_in_cache
>=
0x02000000
)
{
tab
=
DCT_B15_10
+
(
UBITS
(
bs
->
i_bit_in_cache
,
10
)
-
8
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x00800000
)
{
tab
=
DCT_13
+
(
UBITS
(
bs
->
i_bit_in_cache
,
13
)
-
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
if
(
bs
->
i_bit_in_cache
>=
0x00200000
)
{
tab
=
DCT_15
+
(
UBITS
(
bs
->
i_bit_in_cache
,
15
)
-
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
else
{
tab
=
DCT_16
+
UBITS
(
bs
->
i_bit_in_cache
,
16
);
bs_flush
(
bs
,
16
);
i
+=
tab
->
run
;
if
(
i
<
64
)
goto
normal_code
;
}
fprintf
(
stderr
,
"Err in B15
\n
"
);
tr
->
b_error
=
1
;
break
;
/* illegal, check needed to avoid buffer overflow */
}
bs_flush
(
bs
,
4
);
/* dump end of block code */
blk
->
level
=
0
;
if
(
tr
->
mpeg4_matrix
)
quantize_block
(
tr
,
blk
,
1
);
}
int
get_non_intra_block
(
transrate_t
*
tr
,
RunLevel
*
blk
)
{