Compare commits

..

179 Commits

Author SHA1 Message Date
Cullen Jennings
f9bfb31fd2 Update Dockerfile
Junk the hash of .a file
2014-11-29 15:48:23 -07:00
Cullen Jennings
9baaaa2a64 fix line continution problem 2014-11-29 11:40:18 -07:00
Cullen Jennings
d744a1ab19 update .gitignore to ignore emacs temp files 2014-11-27 15:46:29 -07:00
Cullen Jennings
df07fa8adc Test dockerfile to see if we get consistent builds 2014-11-27 15:45:52 -07:00
ruil2
c44d4a7f07 Merge pull request #1569 from mstorsjo/pointer-diff-cast
Add casts when converting pointer differences to integers
2014-11-27 21:54:42 +08:00
Martin Storsjö
917d41bd47 Add casts when converting pointer differences to integers
This fixes warnings when building with MSVC in 64 bit mode.
2014-11-27 11:31:13 +02:00
HaiboZhu
82b70b34fe Merge pull request #1561 from ruil2/cleanup
remove some macro definitions in header files
2014-11-27 14:22:06 +08:00
zhilwang
3a73179cab Merge pull request #1559 from HaiboZhu/EC_off_crash_no_output
Debug for (1) decoder crash when delay decoding (2) no output when EC off
2014-11-27 14:21:48 +08:00
HaiboZhu
69f6db1b90 Merge pull request #1560 from ruil2/max2
cleanup macro definition
2014-11-27 14:21:37 +08:00
HaiboZhu
c2c861f199 Merge pull request #1562 from zhilwang/asm-cabac
Add asm code for decoder cabac
2014-11-27 14:21:02 +08:00
zhiliang wang
92bc88eacb Add asm code for decoder cabac 2014-11-26 16:44:12 +08:00
ruil2
80ce939d7a remove some macro definitions in header files 2014-11-26 16:15:19 +08:00
ruil2
a43fa3aec2 cleanup macro definition 2014-11-26 15:22:04 +08:00
sijchen
e1262a9ac9 Merge pull request #1558 from huili2/comment_outputlog
comment output info with FREEZE
2014-11-25 22:54:43 -08:00
sijchen
fe7faf768a Merge pull request #1555 from huili2/comment_API_parseonly
add parse only comment in API
2014-11-25 22:54:04 -08:00
Haibo Zhu
aa5e7f7927 Remove the SPS/PPS exist ahead reset logic and change the CheckSpsActive logic 2014-11-25 21:53:40 -08:00
huili2
9da19758cf Merge pull request #1556 from ruil2/max2
remove some unused code
2014-11-26 13:33:21 +08:00
huili2
f131b4540b Merge pull request #1557 from dongzha/AddDecoderTimeStampNew
add timestamp in decoder
2014-11-26 13:32:40 +08:00
dong zhang
2e5243e5fc add timestamp in decoder 2014-11-26 13:03:46 +08:00
ruil2
4a6de5bb13 remove some unused code 2014-11-26 10:26:16 +08:00
huili2
347e4893a9 add parse only comment in API 2014-11-25 18:22:23 -08:00
huili2
94dde141fa comment output info with FREEZE 2014-11-25 18:09:01 -08:00
sijchen
f48b2e55ba Merge pull request #1553 from ruil2/max2
add maxbitrate verification
2014-11-25 09:14:39 -08:00
sijchen
7be8d200d5 Merge pull request #1554 from mstorsjo/add-float-cast
Explicitly cast int64_t to float
2014-11-25 09:12:37 -08:00
Martin Storsjö
1ff9de36ce Explicitly cast int64_t to float
This fixes warnings when bulding with MSVC.
2014-11-25 14:28:20 +02:00
ruil2
22cc0a88c6 Merge pull request #1552 from mstorsjo/init-parameters
Initialize the bParseOnly field in DecoderInterfaceTest::TestInitUninit
2014-11-25 17:14:32 +08:00
ruil2
0d426b826d Merge pull request #1551 from sijchen/after_review2
add parentness
2014-11-25 17:13:54 +08:00
ruil2
d543ae89db add maxbitrate verification 2014-11-25 17:12:06 +08:00
Martin Storsjö
29da6a600a Initialize the bParseOnly field in DecoderInterfaceTest::TestInitUninit
This fixes valgrind warnings about using uninitialized data
in this test.
2014-11-25 09:59:25 +02:00
Sijia Chen
cef85118b5 add parentness 2014-11-24 22:44:06 -08:00
huili2
305a2421be Merge pull request #1549 from dongzha/ECMvCopy
add EC MV copy
2014-11-25 12:59:48 +08:00
ruil2
f1fb0d6b69 Merge pull request #1548 from sijchen/after_review
[Encoder] add one more condition for statistics printing to avoid potential timestamp problem
2014-11-25 11:20:38 +08:00
dong zhang
9425c2ab10 add EC MV copy 2014-11-25 10:45:58 +08:00
Sijia Chen
3be7e90221 add one more conditin for statistics printing to avoid timestamp problem 2014-11-24 16:11:52 -08:00
sijchen
48e79d51b5 Merge pull request #1547 from huili2/ParseDecode
parse only add and UT: passed reviewed at https://rbcommons.com/s/OpenH264/r/910/
2014-11-24 11:28:17 -08:00
sijchen
336b2d1537 Merge pull request #1542 from sijchen/review
[Encoder] refactor Sps generation: passed review at https://rbcommons.com/s/OpenH264/r/930/
2014-11-24 11:27:38 -08:00
huili2
b231e3f000 parse only add and UT 2014-11-24 00:04:36 -08:00
sijchen
53c14dccf0 Merge pull request #1545 from ruil2/add_traces
add some traces
2014-11-21 14:01:43 -08:00
ruil2
3025c58a67 add some traces 2014-11-21 13:27:10 +08:00
ruil2
a0b0866597 Merge pull request #1543 from dongzha/Fix1535
Check and Fix some issue #1535
2014-11-21 11:30:36 +08:00
ruil2
1359583c55 Merge pull request #1544 from shihuade/master
1.doxgen documentation format for comments in api/*.h 2. comments to wik...
2014-11-21 11:29:34 +08:00
huashi
7175d3c90e 1.doxgen documentation format for comments in api/*.h 2. comments to wiki tools in openh264/docs/* 2014-11-21 10:38:30 +08:00
Sijia Chen
cdd410ca66 refactor Sps generation 2014-11-20 12:55:48 -08:00
ruil2
24fb213d6e Merge pull request #1537 from sijchen/after_review
[Encoder] Two refinements related to max bit rate setting and Timestamp
2014-11-20 09:33:36 +08:00
Sijia Chen
0b2c82d92b add UNSPECIFIED value for max bit rate setting 2014-11-19 16:05:19 -08:00
Sijia Chen
810b9770fc using same type as in interface rather than int32 for uiTimestamp to avoid missing of preciseness 2014-11-19 15:45:09 -08:00
dong zhang
b18e905946 Check and Fix some issue#1535 2014-11-19 16:03:34 +08:00
ruil2
c13bfe6407 Merge pull request #1536 from sijchen/improve_br_valid
[Encoder] adjust the param validation of max bit rate
2014-11-18 18:42:03 +08:00
sijchen
0252f3f346 Merge pull request #1526 from ruil2/max_nal_size
add return value processing
2014-11-17 16:43:45 -08:00
sijchen
b05a52be7a Merge pull request #1534 from syureyi/level9
add level 9 supporting
2014-11-17 16:43:37 -08:00
Sijia Chen
7e24efc620 adjust the param validation of max bit rate 2014-11-17 16:39:42 -08:00
zhuiling
02853a9a96 add level 9 supporting 2014-11-17 16:29:33 +08:00
dongzha
cbb6e993cf Merge pull request #1533 from mstorsjo/speedup-tests
Speed up some slow tests in the unit test suite
2014-11-14 17:16:06 +08:00
dongzha
bfee07dde4 Merge pull request #1532 from huili2/new_EC_IDR_reschange
add EC method to freeze sequence when resolution changed and decoding IDR error
2014-11-14 17:14:09 +08:00
Martin Storsjö
deefdcee10 Use & 0xff instead of WELS_CLIP3(, 0, 255)
This speeds up the whole EncoderInterfaceTest to about double
the speed from before.
2014-11-14 10:41:21 +02:00
Martin Storsjö
45c322a8ae Reduce the number of rounds in DecoderCrashTest
Currently this one single test accounts for 12-20% of the total
runtime of running the unit test suite.
2014-11-14 10:41:21 +02:00
ruil2
606da1a97d Merge pull request #1531 from mstorsjo/use-right-type
Use the right data type for a variable
2014-11-14 16:30:17 +08:00
Martin Storsjö
9ec743c156 Use the right data type for a variable
Both pNalLengthInByte[] that are accumulated, and sFbi.iFrameSizeInBytes
that it is compared to, are plain 'int', not 'uint32_t'.

This fixes warnings about comparison between signed and unsigned.
2014-11-14 09:47:49 +02:00
huili2
0d16fd61b2 add EC method to freeze sequence when resolution changed and decoding IDR error 2014-11-13 19:26:10 -08:00
ruil2
703bbef128 Merge pull request #1530 from sijchen/after_review
[Encoder] add total length in encoder output and complete statistics
2014-11-14 11:20:45 +08:00
Sijia Chen
b56b8725fc add total length in encoder output and complete most of the statistis calculation 2014-11-13 13:56:58 -08:00
ruil2
aed7b2316c Merge pull request #1528 from mstorsjo/fix-warnings
Cast to the right data type to avoid comparison warnings in gcc
2014-11-13 17:17:41 +08:00
Martin Storsjö
2453676960 Cast to the right data type to avoid comparison warnings in gcc 2014-11-13 10:48:45 +02:00
HaiboZhu
7a2e536e44 Merge pull request #1525 from dongzha/FixbuginMVClip
fix mv clip at right boarder
2014-11-13 14:01:45 +08:00
ruil2
66165a65d5 add return value processing 2014-11-13 13:26:14 +08:00
sijchen
b3922b1d3a Merge pull request #1519 from ruil2/max_nal_size
add maxnalsize control for gmp wrapper
2014-11-12 20:44:24 -08:00
dong zhang
e4f114e006 fix mv clip at right boarder 2014-11-13 10:48:35 +08:00
dongzha
429ccb38a8 Merge pull request #1524 from huili2/parse_err_return_bug_fix
fix bug of parse error return for VCL data
2014-11-12 13:18:08 +08:00
ruil2
9ba0a1d977 Merge pull request #1522 from sijchen/after_review
[Encoder] fix a calculation of fAverageFrameRate
2014-11-12 12:29:13 +08:00
huili2
2527cf5d0b fix bug of parse error return for VCL data 2014-11-11 19:23:58 -08:00
Sijia Chen
cd5928d397 fix a calculation of fAverageFrameRate 2014-11-11 16:12:38 -08:00
sijchen
f42c9fae42 Merge pull request #1518 from huili2/ec_UT_0_bugfix
EC UT fail bug fix
2014-11-11 14:52:28 -08:00
sijchen
a37f1abe5e Merge pull request #1517 from ruil2/cabac_qp
fix cabac encoding bug -- don't get the correct previous mb qp
2014-11-11 14:52:04 -08:00
ruil2
128546b992 add maxnalsize control for gmp wrapper 2014-11-11 14:18:02 +08:00
ruil2
560fcf17fd rename parameters 2014-11-11 12:21:01 +08:00
huili2
fd45e7ff15 EC UT fail bug fix 2014-11-10 17:56:26 -08:00
sijchen
9512515a41 Merge pull request #1515 from ruil2/add_nal_trace
add some traces for bitstream output
2014-11-10 15:00:08 -08:00
ruil2
24823621e1 Merge pull request #1516 from mstorsjo/remove-duplicated-field
Remove a duplicated field in SWelsSvcCodingParam
2014-11-10 15:56:51 +08:00
ruil2
c31511257b fix cabac encoding bug -- don't get the correct previous mb qp 2014-11-10 15:34:49 +08:00
ruil2
1c44c43b8a add some traces for bitstream output 2014-11-10 15:20:25 +08:00
Martin Storsjö
0aa77d2985 Remove a duplicated field in SWelsSvcCodingParam
The same field already exists in SEncParamExt. When the
initialization was deduplicated in ac404ce, this lead to
reading the now uninitialized field in SWelsSvcCodingParam,
instead of the properly initialized one in the base class.
2014-11-10 09:03:18 +02:00
sijchen
8b49f98475 Merge pull request #1507 from ruil2/init
remove repeat initialization
2014-11-09 18:07:21 -08:00
ruil2
fc811a80fb Merge pull request #1512 from mstorsjo/add-float-cast
Add a cast when converting from double to float
2014-11-09 09:36:21 +08:00
ruil2
843955bc06 Merge pull request #1511 from mstorsjo/check-fread-return-value
Check the return value of fread
2014-11-09 09:35:26 +08:00
Ethan Hugg
a7b22795bf Merge pull request #1510 from mstorsjo/unsigned-int-literals
Change integer literals to unsigned to avoid warnings about comparison between signed and unsigned
2014-11-07 09:49:00 -08:00
Ethan Hugg
3c753c42b8 Merge pull request #1509 from mstorsjo/fix-warnings-cast
Add casts to avoid warnings about comparison between signed and unsigned
2014-11-07 09:46:33 -08:00
Ethan Hugg
067fa09781 Merge pull request #1508 from mstorsjo/remove-unused-variables
Remove unused variables
2014-11-07 09:45:52 -08:00
Martin Storsjö
c8afd15681 Add a cast when converting from double to float
This fixes warnings with MSVC.
2014-11-07 11:41:59 +02:00
Martin Storsjö
80bfc43df5 Check the return value of fread
This silences warnings on linux/gcc.
2014-11-07 11:24:30 +02:00
Martin Storsjö
50e2eb5e3c Change integer literals to unsigned to avoid warnings about comparison between signed and unsigned
This fixes warnings in gcc.
2014-11-07 11:19:19 +02:00
Martin Storsjö
2b9f4f6607 Add casts to avoid warnings about comparison between signed and unsigned
This fixes warnings with gcc.
2014-11-07 11:17:44 +02:00
Martin Storsjö
08c07e4b8f Remove unused variables
This fixes warnings with clang and gcc.
2014-11-07 11:12:51 +02:00
ruil2
ac404ce69d remove repeat initialization 2014-11-07 14:58:43 +08:00
HaiboZhu
44013d4cd5 Merge pull request #1504 from syureyi/android_bugfix
android platform bug fix
2014-11-06 21:31:03 +08:00
dongzha
789603a8b1 Merge pull request #1503 from huili2/ec_crossIDR
enable cross IDR EC method
2014-11-06 17:24:17 +08:00
zhuiling
7fa6c576e3 android platform bug fix 2014-11-06 17:15:42 +08:00
dongzha
0fa667ac5f Merge pull request #1502 from dongzha/RemoveUglyCode
remove ugly MC code
2014-11-06 15:26:38 +08:00
dongzha
1a7826c6eb remove ugly MC code 2014-11-06 14:44:33 +08:00
sijchen
5cb5c28331 Merge pull request #1500 from syureyi/decoderstatics
decoder statictis adding
2014-11-06 14:25:04 +08:00
zhuling13
45ef803e4d decoder statictis adding
mem

mem

decstatictis

time change

time change

set decTime=0
2014-11-05 22:01:32 -08:00
huili2
3d21825901 Merge pull request #1497 from dongzha/FixCabacBug
fix cabac bug in deltaqp
2014-11-06 12:19:13 +08:00
dongzha
ba0351f569 fix cabac bug in deltaqp 2014-11-06 10:51:18 +08:00
sijchen
63180b9b36 Merge pull request #1494 from huili2/ec_final_crash_UT
add a simple UT for debugging decoder crash
2014-11-05 14:24:54 +08:00
ruil2
8ed4e83e93 Merge pull request #1490 from sijchen/after_review
[Encoder] Fixing for large number of slices
2014-11-04 15:12:38 +08:00
huili2
32697b046b add a simple UT for debugging decoder crash 2014-11-03 23:05:34 -08:00
sijchen
b896faa47c Merge pull request #1493 from ruil2/printf
use %lld instead of %8d for longlong type
2014-11-04 14:30:36 +08:00
huili2
103fa5bbed enable cross IDR EC method 2014-11-03 22:11:49 -08:00
ruil2
fe55d5a208 update timestamp unit as millisecond 2014-11-04 11:28:35 +08:00
ruil2
18ed25fbb3 use %lld instead of %8d for longlong type 2014-11-04 10:37:23 +08:00
sijchen
783daf3d8a Merge pull request #1485 from ruil2/cabac_refine
pass each frame timestamp to codec
2014-11-04 09:31:07 +08:00
Sijia Chen
54c677cdd7 fixing OverallMbMap for slice_idx>255 and some log improvements 2014-11-04 09:19:36 +08:00
sijchen
08baf65251 Merge pull request #1488 from mstorsjo/fix-warnings
Fix warnings with gcc and MSVC
2014-11-04 09:13:55 +08:00
sijchen
ca1c357058 Merge pull request #1486 from mstorsjo/fix-pow-params
Don't try to use pow(int,int)
2014-11-04 09:13:46 +08:00
Martin Storsjö
8ffacf0918 Add casts to avoid warnings about comparison between signed and unsigned
This fixes warnings with gcc and msvc.
2014-11-03 11:28:40 +02:00
Martin Storsjö
0e9541247a Use the right data type for some local variables
pDecEngine->uiOffset is an uint64_t as well, and *pSliceNum
is uint32_t.

This fixes warnings about comparison between signed and unsigned
in gcc and msvc.
2014-11-03 11:28:35 +02:00
Martin Storsjö
c1b48640fb Don't try to use pow(int,int)
When building for android or older MSVC versions, this makes the build
fail, when it is ambiguous which pow() overload to use, when there
is no function matching pow(int, int).
2014-11-03 11:23:10 +02:00
ruil2
c5029ef275 Merge pull request #1484 from mstorsjo/fix-chmod
Remove the executable bit from new test sequences
2014-11-03 17:10:44 +08:00
ruil2
e061bb3fc9 pass each frame timestamp to codec 2014-11-03 17:05:38 +08:00
Martin Storsjö
2951a7f3a3 Remove variables that are set but not used
This fixes build warnings with gcc.
2014-11-03 10:52:02 +02:00
Martin Storsjö
7478714ac9 Remove the executable bit from new test sequences 2014-11-03 10:10:17 +02:00
sijchen
9ac2d2ad85 Merge pull request #1483 from dongzha/EnhanceDecConsole
modify console code for Demo interfaces test (this is reviewed at: https://rbcommons.com/s/OpenH264/r/890/)
2014-11-03 15:41:42 +08:00
sijchen
dbd4330508 Merge pull request #1482 from ruil2/cabac_refine
add setoption trace
2014-11-03 15:39:45 +08:00
sijchen
938f441751 Merge pull request #1480 from dongzha/cleanCabacDecoder
add decoder cabac support and add  UT
2014-11-03 15:38:24 +08:00
dong zhang
880e0fff06 modify macro STICK_STREAM_SIZE // For Demo interfaces test with track file of integrated frames
add macro NO_DELAY_DECODING	// For Demo interfaces test with no delay decoding
2014-11-03 11:26:14 +08:00
ruil2
c19db25043 add setoption trace 2014-11-03 10:37:07 +08:00
dong zhang
cf85745752 add decoder cabac support and add UT 2014-11-03 10:03:43 +08:00
sijchen
c7b5051738 Merge pull request #1469 from shihuade/APIUTV1.5.2
refactor --for BaseEncoderTest
2014-11-03 09:31:11 +08:00
ruil2
07bf80ba39 Merge pull request #1476 from mstorsjo/sps-constraints
Set constraint set 0 and 1 flags for non-scalable as well
2014-11-03 09:29:26 +08:00
Martin Storsjö
53e2f67e80 Set constraint set 0 and 1 flags for non-scalable as well
This allows decoders to know that a baseline stream doesn't
contain any of the features that aren't in the constrained
baseline subset.

Set the flags based on what profile we target.
2014-10-31 10:48:09 +02:00
ruil2
3abd54ca73 Merge pull request #1477 from mstorsjo/avoid-msvc-warnings
Avoid warnings when building with MSVC
2014-10-31 15:36:14 +08:00
ruil2
8e49898243 Merge pull request #1478 from sijchen/after_review61
[Encoder] add validation of slice parameters instead of assert
2014-10-31 15:34:37 +08:00
sijchen
66b1610114 Merge pull request #1472 from mstorsjo/fix-test-random
Make sure the width/height is large enough in SetOptionEncParamExt
2014-10-31 13:50:10 +08:00
Sijia Chen
24192cc235 add validation of slice parameters instead of assert 2014-10-30 18:31:50 +08:00
Martin Storsjö
655f3b43b6 Add a cast when converting from int64_t to float
This avoids a warning when building with MSVC.
2014-10-30 11:07:22 +02:00
Martin Storsjö
a291470072 Avoid warnings about converting from int to bool
MSVC used to warn about this.
2014-10-30 11:06:46 +02:00
Martin Storsjö
ec0d151879 Make sure the width/height is large enough in SetOptionEncParamExt
When using 4 downsampled layers, make sure the random width/height
is large enough that the downsampled layers don't have a zero size.

Since the value never will be too small now, there's no need to
use WELS_CLIP3 any longer.
2014-10-30 08:54:18 +02:00
dongzha
3b5448cbbc Merge pull request #1475 from ruil2/cabac_refine
Cabac refine
2014-10-30 13:39:46 +08:00
ruil2
055915d720 update windows project for table change 2014-10-30 12:47:26 +08:00
ruil2
100de97b49 move cabac table to common 2014-10-30 12:42:09 +08:00
sijchen
3a1f0a3d95 Merge pull request #1471 from mstorsjo/fix-warnings
Remove unused variables and an impossible condition
2014-10-30 09:10:08 +08:00
sijchen
41ed734674 Merge pull request #1473 from mstorsjo/silence-test-warnings
Silence warning logging while running tests that can produce errors
2014-10-30 09:08:55 +08:00
sijchen
b8e0a3fa38 Merge pull request #1474 from mstorsjo/use-proper-logging
Use WelsLog instead of fprintf for normal runtime errors
2014-10-30 08:21:28 +08:00
Martin Storsjö
7ce4da8a41 Use WelsLog instead of fprintf for normal runtime errors 2014-10-29 22:45:44 +02:00
Martin Storsjö
1c2940479d Silence warning logging while running tests that can produce errors 2014-10-29 22:44:40 +02:00
Martin Storsjö
2907cb2875 Remove an impossible condition
uiIntraPeriod is unsigned, and thus can't ever be negative.

The subtraction on the line above can't ever make the value wrap
around either, since param_.uiIntraPeriod % uiGOPSize always is
smaller than or equal to param_.uiIntraPeriod. Thus, the check
never is necessary even if the value would be signed either.

This fixes warnings when building with clang.
2014-10-29 22:07:21 +02:00
Martin Storsjö
a625dc836d Remove unused variables 2014-10-29 22:07:20 +02:00
Ethan Hugg
9be23c7821 Merge pull request #1470 from mstorsjo/fix-chmod
Remove the executable bit from the API docs
2014-10-29 11:43:13 -07:00
Martin Storsjö
7f645bf2f7 Remove the executable bit from the API docs 2014-10-29 20:33:26 +02:00
huashi
54c24dfd60 refactor --for BaseEncoderTest 2014-10-29 17:53:08 +08:00
ruil2
c83ab3bca1 Merge pull request #1462 from sijchen/after_review1
updated documents from v1.2
2014-10-29 17:17:38 +08:00
ruil2
58cc29225e Merge pull request #1463 from sijchen/after_review4
[Encoder] for reference selection under screen
2014-10-29 17:17:07 +08:00
sijchen
d3a971e32c Merge pull request #1466 from shihuade/APIUTV1.5
set option for ParamExt----random cases
2014-10-29 14:41:46 +08:00
ruil2
329ccd7d6f Merge pull request #1464 from mstorsjo/unify-msvc-nasm
Revert unrelated changes to MSVC project file nasm commands
2014-10-29 09:55:20 +08:00
ruil2
f10f6a788f Merge pull request #1467 from mstorsjo/cabac-stash-fix
Don't stash the cabac state into the SBitStringAux buffer
2014-10-29 09:28:06 +08:00
Martin Storsjö
f84560474c Revert unrelated changes to MSVC project file nasm commands
The cabac encoder commit accidentally changed some of the nasm
commands in the MSVC project file, that were previously
made consistent in b17e9bb32 and 7720f2cc5.
2014-10-28 23:38:14 +02:00
Martin Storsjö
f2c1395ab6 Remove the pBuffer parameter from the entropy encoder stash functions
The parameter didn't make sense since it only pointed to the
pSliceBsa field, which isn't what should be used to stash
the cabac context.
2014-10-28 14:59:50 +02:00
Martin Storsjö
9a9f92bcfe Don't stash the cabac state into the SBitStringAux buffer
This fixes crashes on some platforms, and fixes valgrind
errors.
2014-10-28 14:59:50 +02:00
huashi
26615fffd0 set option for ParamExt----random cases 2014-10-28 20:36:33 +08:00
Sijia Chen
a2d5254bc3 update VERSION in Makefile 2014-10-28 17:57:57 +08:00
Sijia Chen
4fab8c2ee7 for reference selection under screen:
1, ref_list_mgr_svc.cpp, Ln314: fix a wrong DeleteLTRFromLongList which should not be used under screen strategy
2, ref_list_mgr_svc.cpp, Ln910: remove the frame which is furthest in distance to the current frame in ref list
3, wels_preprocess.cpp: use scene LTR ref list when the current frame is scene LTR
-, ref_list_mgr_svc.cpp, Ln811: add DEBUG trace
reviewed at: https://rbcommons.com/s/OpenH264/r/870/
2014-10-28 16:58:59 +08:00
sijchen
292d2511e2 Merge pull request #1457 from ruil2/enc_cabac
add encoder cabac support
2014-10-28 16:51:56 +08:00
Sijia Chen
4292f91ae5 add updated documents from v1.2 2014-10-28 13:55:37 +08:00
Ethan Hugg
5cefad2d3f Merge pull request #1460 from zaheerm/pkgconfig
Add .pc file generation to PHONY targets
2014-10-27 10:48:30 -07:00
Ethan Hugg
fcb84f5fb6 Merge pull request #1459 from tp-m/pkgconfig-install-fix
Fix openh264.pc file installation
2014-10-27 10:01:41 -07:00
Zaheer Abbas Merali
fe621b92bf Add .pc file generation to PHONY targets as version change in Makefile needs to cause a rebuild. 2014-10-27 10:00:13 -07:00
Tim-Philipp Müller
1ad797a81e Fix openh264.pc file installation
If there's no pkgconfig subdirectory yet in our
install prefix, create it first, otherwise we'll
end up with a file called 'pkgconfig' instead.
2014-10-27 16:22:58 +00:00
Ethan Hugg
9a72378c34 Merge pull request #1455 from zaheerm/pkgconfig
Add pkg-config file.
2014-10-27 09:01:18 -07:00
ruil2
ec901a14d6 Merge pull request #1456 from dongzha/fixRCOverFlow
fix Rc int32_t bitrate overflow
2014-10-27 13:08:54 +08:00
ruil2
abc01e6b81 add encoder cabac support 2014-10-27 13:06:33 +08:00
dong zhang
d3c8ade8d0 fix Rc int32_t bitrate overflow 2014-10-27 09:54:44 +08:00
Zaheer Abbas Merali
46d30cd33c Add pkg-config file. 2014-10-26 15:26:52 -07:00
ruil2
2dbb757d30 Merge pull request #1451 from sijchen/for_format
Fixes and change naming
2014-10-24 15:18:55 +08:00
sijchen
34cb0d60aa Merge pull request #1450 from mstorsjo/avoid-warnings
Add casts to avoid warnings about comparison between signed and unsigned
2014-10-24 14:41:51 +08:00
Sijia Chen
6a2a4efef6 fix names to keep consistent of style
improve UT to cover more cases under GetStatistics
2014-10-24 14:39:50 +08:00
Sijia Chen
ea9b80adb3 fix a wrong range clip 2014-10-24 14:12:53 +08:00
sijchen
468fce0887 Merge pull request #1448 from sijchen/for_format
roll back the file which is mis-formatted by astyle
2014-10-24 14:12:40 +08:00
Martin Storsjö
f0c6891627 Add casts to avoid warnings about comparison between signed and unsigned 2014-10-24 09:05:32 +03:00
Sijia Chen
50fd617e86 roll back the file which is mis-formatted by astyle 2014-10-24 13:04:35 +08:00
ruil2
ac290d65c7 Merge pull request #1446 from sijchen/for_format
[Encoder] fix a small range of slice idx
2014-10-24 12:50:07 +08:00
128 changed files with 16341 additions and 10150 deletions

7
.gitignore vendored
View File

@@ -44,3 +44,10 @@ testbin/test_vd_rc.264
testbin/test_vd_rc.yuv
testbin/test.264
testbin/test.yuv
# pkg-config file
*.pc
# editor files
*~

View File

@@ -26,6 +26,7 @@ PROJECT_NAME=openh264
MODULE_NAME=gmpopenh264
GMP_API_BRANCH=master
CCASFLAGS=$(CFLAGS)
VERSION=1.2
ifeq (,$(wildcard $(SRC_PATH)gmp-api))
HAVE_GMP_API=No
@@ -122,7 +123,7 @@ API_TEST_INCLUDES += $(CODEC_UNITTEST_INCLUDES) -I$(SRC_PATH)test -I$(SRC_PATH)t
COMMON_UNITTEST_INCLUDES += $(CODEC_UNITTEST_INCLUDES) $(DECODER_INCLUDES) -I$(SRC_PATH)test -I$(SRC_PATH)test/common
MODULE_INCLUDES += -I$(SRC_PATH)gmp-api
.PHONY: test gtest-bootstrap clean
.PHONY: test gtest-bootstrap clean $(PROJECT_NAME).pc
all: libraries binaries
@@ -206,6 +207,9 @@ $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIX): $(MODULE_OBJS) $(ENCODER_OBJS) $(
$(QUIET)rm -f $@
$(QUIET_CXX)$(CXX) $(SHARED) $(CXX_LINK_O) $+ $(LDFLAGS) $(SHLDFLAGS) $(MODULE_LDFLAGS)
$(PROJECT_NAME).pc: $(PROJECT_NAME).pc.in
@sed -e 's;@prefix@;$(PREFIX);' -e 's;@VERSION@;$(VERSION);' < $(PROJECT_NAME).pc.in > $(PROJECT_NAME).pc
install-headers:
mkdir -p $(PREFIX)/include/wels
install -m 644 codec/api/svc/codec*.h $(PREFIX)/include/wels
@@ -214,9 +218,11 @@ install-static: $(LIBPREFIX)$(PROJECT_NAME).$(LIBSUFFIX) install-headers
mkdir -p $(PREFIX)/lib
install -m 644 $(LIBPREFIX)$(PROJECT_NAME).$(LIBSUFFIX) $(PREFIX)/lib
install-shared: $(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIX) install-headers
install-shared: $(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIX) install-headers $(PROJECT_NAME).pc
mkdir -p $(PREFIX)/lib
install -m 755 $(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIX) $(PREFIX)/lib
mkdir -p $(PREFIX)/lib/pkgconfig
install -m 444 $(PROJECT_NAME).pc $(PREFIX)/lib/pkgconfig
ifneq ($(EXTRA_LIBRARY),)
install -m 644 $(EXTRA_LIBRARY) $(PREFIX)/lib
endif

Binary file not shown.

51
build/Dockerfile Normal file
View File

@@ -0,0 +1,51 @@
# This is a docker image with all the tools to build openh264 for linux
# build the docker image with: sudo docker build -t openh264tools - < Dockerfile
# get the result with: sudo docker run -t -i -v /tmp/openH264:/build openh264tools /bin/cp libopenh264.so log /build
# the results will be left in /tmp/openH264
# have a look at log file and if the hash match the "Fluffy got" hashes
FROM ubuntu:14.04
MAINTAINER Cullen Jennings <fluffy@cisco.com>
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y bison flex g++ gcc git libgmp3-dev libmpc-dev libmpfr-dev libz-dev make wget
WORKDIR /tmp
RUN wget http://ftp.gnu.org/gnu/gcc/gcc-4.9.2/gcc-4.9.2.tar.gz
RUN tar xvfz gcc-4.9.2.tar.gz
WORKDIR /tmp/gcc-4.9.2/
RUN mkdir build
WORKDIR /tmp/gcc-4.9.2/build
RUN ../configure --disable-checking --enable-languages=c,c++ --enable-multiarch --enable-shared --enable-threads=posix --with-gmp=/usr/local/lib --with-mpc=/usr/lib --with-mpfr=/usr/lib --without-included-gettext --with-system-zlib --with-tune=generic --disable-multilib --disable-nls
RUN make -j 8
RUN make install
WORKDIR /tmp
RUN wget http://www.nasm.us/pub/nasm/releasebuilds/2.11.06/nasm-2.11.06.tar.gz
RUN tar xvfz nasm-2.11.06.tar.gz
WORKDIR /tmp/nasm-2.11.06/
RUN ./configure
RUN make
RUN make install
WORKDIR /tmp
RUN git clone https://github.com/cisco/openh264.git
WORKDIR /tmp/openh264
RUN git checkout v1.1
RUN make ENABLE64BIT=Yes
RUN date > log
RUN uname -a >> log
RUN nasm -v >> log
RUN gcc -v 2>> log
RUN git status -v >> log
RUN openssl dgst -sha1 libopenh264.so >> log
RUN echo "Fluffy Got hash of - 3b6280fce36111ab9c911453f4ee1fd99ce6f841" >> log

View File

@@ -1,4 +1,6 @@
/*!
*@page License
*
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
@@ -50,73 +52,361 @@ typedef unsigned char bool;
#define EXTAPI
#endif
/**
* @file codec_api.h
*/
/**
* @page Overview
* * This page is for openh264 codec API usage.
* * For how to use the encoder,please refer to page UsageExampleForEncoder
* * For how to use the decoder,please refer to page UsageExampleForDecoder
* * For more detail about ISVEncoder,please refer to page ISVCEnoder
* * For more detail about ISVDecoder,please refer to page ISVCDecoder
*/
/**
* @page DecoderUsageExample
*
* @brief
* * An example for using the decoder for Decoding only or Parsing only
*
* Step 1:decoder declaration
* @code
*
* //decoder declaration
* ISVCDecoder *pSvcDecoder;
* //input: encoded bitstream start position; should include start code prefix
* unsigned char *pBuf =...;
* //input: encoded bit stream length; should include the size of start code prefix
* int iSize =...;
* //output: [0~2] for Y,U,V buffer for Decoding only
* unsigned char *pData[3] =...;
* //in-out: for Decoding only: declare and initialize the output buffer info, this should never co-exist with Parsing only
* SBufferInfo sDstBufInfo;
* memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
* //in-out: for Parsing only: declare and initialize the output bitstream buffer info for parse only, this should never co-exist with Decoding only
* SParserBsInfo sDstParseInfo;
* memset(&sDstParseInfo, 0, sizeof(SParserBsInfo));
* sDstParseInfo.pDstBuff = new unsigned char[PARSE_SIZE]; //In Parsing only, allocate enough buffer to save transcoded bitstream for a frame
*
* @endcode
*
* Step 2:decoder creation
* @code
* CreateDecoder(pSvcDecoder);
* @endcode
*
* Step 3:declare required parameter, used to differentiate Decoding only and Parsing only
* @code
* SDecodingParam sDecParam = {0};
* sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
* //for Parsing only, the assignment is mandatory
* sDecParam.bParseOnly = true;
* @endcode
*
* Step 4:initialize the parameter and decoder context, allocate memory
* @code
* Initialize(&sDecParam);
* @endcode
*
* Step 5:do actual decoding process in slice level;
* this can be done in a loop until data ends
* @code
* //for Decoding only
* iRet = DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
* //for Parsing only
* iRet = DecodeParser(pBuf, iSize, &sDstParseInfo);
* //decode failed
* If (iRet != 0){
* RequestIDR or something like that.
* }
* //for Decoding only, pData can be used for render.
* if (sDstBufInfo.iBufferStatus==1){
* output pData[0], pData[1], pData[2];
* }
* //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
* if (sDstBufInfo.iBufferStatus==1){
* Hardware decoding sDstParseInfo;
* }
* //no-delay decoding can be realized by directly calling decoder again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
* iRet = DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
* judge iRet, sDstBufInfo.iBufferStatus ...
* @endcode
*
* Step 6:uninitialize the decoder and memory free
* @code
* Uninitialize();
* @endcode
*
* Step 7:destroy the decoder
* @code
* DestroyDecoder();
* @endcode
*
*/
/**
* @page EncoderUsageExample1
*
* @brief
* * An example for using encoder with basic parameter
*
* Step1:setup encoder
* @code
* int rv = WelsCreateSVCEncoder (&encoder_);
* ASSERT_EQ (0, rv);
* ASSERT_TRUE (encoder_ != NULL);
* @endcode
*
* Step2:initilize with basic parameter
* @code
* SEncParamBase param;
* memset (&param, 0, sizeof (SEncParamBase));
* param.iUsageType = usageType;
* param.fMaxFrameRate = frameRate;
* param.iPicWidth = width;
* param.iPicHeight = height;
* param.iTargetBitrate = 5000000;
* param.iInputCsp = videoFormatI420;
* encoder_->Initialize (&param);
* @endcode
*
* Step3:set option, set option during encoding process
* @code
* encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
* @endcode
*
* Step4: encode and store ouput bistream
* @code
* int frameSize = width * height * 3 / 2;
* BufferedData buf;
* buf.SetLength (frameSize);
* ASSERT_TRUE (buf.Length() == (size_t)frameSize);
* SFrameBSInfo info;
* memset (&info, 0, sizeof (SFrameBSInfo));
* SSourcePicture pic;
* memset (&pic, 0, sizeof (SsourcePicture));
* pic.iPicWidth = width;
* pic.iPicHeight = height;
* pic.iColorFormat = videoFormatI420;
* pic.iStride[0] = pic.iPicWidth;
* pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
* pic.pData[0] = buf.data();
* pic.pData[1] = pic.pData[0] + width * height;
* pic.pData[2] = pic.pData[1] + (width * height >> 2);
* for(int num = 0;num<total_num;num++) {
* //prepare input data
* rv = encoder_->EncodeFrame (&pic, &info);
* ASSERT_TRUE (rv == cmResultSuccess);
* if (info.eFrameType != videoFrameTypeSkip && cbk != NULL) {
* //output bitstream
* }
* }
* @endcode
*
* Step5:teardown encoder
* @code
* if (encoder_) {
* encoder_->Uninitialize();
* WelsDestroySVCEncoder (encoder_);
* }
* @endcode
*
*/
/**
* @page EncoderUsageExample2
*
* @brief
* * An example for using the encoder with extension parameter.
* * The same operation on Step 1,3,4,5 with Example-1
*
* Step 2:initialize with extension parameter
* @code
* SEncParamExt param;
* encoder->GetDefaultParams (&param);
* param.iUsageType = usageType;
* param.fMaxFrameRate = frameRate;
* param.iPicWidth = width;
* param.iPicHeight = height;
* param.iTargetBitrate = 5000000;
* param.iInputCsp = videoFormatI420;
* param.bEnableDenoise = denoise;
* param.iSpatialLayerNum = layers;
* //SM_DYN_SLICE don't support multi-thread now
* if (sliceMode != SM_SINGLE_SLICE && sliceMode != SM_DYN_SLICE)
* param.iMultipleThreadIdc = 2;
*
* for (int i = 0; i < param.iSpatialLayerNum; i++) {
* param.sSpatialLayers[i].iVideoWidth = width >> (param.iSpatialLayerNum - 1 - i);
* param.sSpatialLayers[i].iVideoHeight = height >> (param.iSpatialLayerNum - 1 - i);
* param.sSpatialLayers[i].fFrameRate = frameRate;
* param.sSpatialLayers[i].iSpatialBitrate = param.iTargetBitrate;
*
* param.sSpatialLayers[i].sSliceCfg.uiSliceMode = sliceMode;
* if (sliceMode == SM_DYN_SLICE) {
* param.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 600;
* param.uiMaxNalSize = 1500;
* }
* }
* param.iTargetBitrate *= param.iSpatialLayerNum;
* encoder_->InitializeExt (&param);
*
* @endcode
*/
#ifdef __cplusplus
/**
* @brief Endocder definition
*/
class ISVCEncoder {
public:
/*
* return: CM_RETURN: 0 - success; otherwise - failed;
*/
/**
* @brief Initialize the encoder
* @param pParam basic encoder parameter
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI Initialize (const SEncParamBase* pParam) = 0;
/**
* @brief Initilaize encoder by using extension parameters.
* @param pParam extension parameter for encoder
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) = 0;
/**
* @brief Get the default extension parameters.
* If you want to change some parameters of encoder, firstly you need to get the default encoding parameters,
* after that you can change part of parameters you want to.
* @param pParam extension parameter for encoder
* @return CM_RETURN: 0 - success; otherwise - failed;
* */
virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) = 0;
/// uninitialize the encoder
virtual int EXTAPI Uninitialize() = 0;
/*
* return: 0 - success; otherwise -failed;
*/
/**
* @brief Encode one frame
* @param kpSrcPic the pointer to the source luminance plane
* chrominance data:
* CbData = kpSrc + m_iMaxPicWidth * m_iMaxPicHeight;
* CrData = CbData + (m_iMaxPicWidth * m_iMaxPicHeight)/4;
* the application calling this interface needs to ensure the data validation between the location
* @param pBsInfo output bit stream
* @return 0 - success; otherwise -failed;
*/
virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) = 0;
/*
* return: 0 - success; otherwise - failed;
*/
/**
* @brief Encode the parameters from output bit stream
* @param pBsInfo output bit stream
* @return 0 - success; otherwise - failed;
*/
virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) = 0;
/*
* return: 0 - success; otherwise - failed;
*/
/**
* @brief Force encoder to encoder frame as IDR if bIDR set as true
* @param bIDR true: force encoder to encode frame as IDR frame;false, return 1 and nothing to do
* @return 0 - success; otherwise - failed;
*/
virtual int EXTAPI ForceIntraFrame (bool bIDR) = 0;
/************************************************************************
* InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,..
************************************************************************/
/*
* return: CM_RETURN: 0 - success; otherwise - failed;
*/
/**
* @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
* @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
/**
* @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
* @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
virtual ~ISVCEncoder() {}
};
/**
* @brief Decoder definition
*/
class ISVCDecoder {
public:
/**
* @brief Initilaize decoder
* @param pParam parameter for decoder
* @return 0 - success; otherwise - failed;
*/
virtual long EXTAPI Initialize (const SDecodingParam* pParam) = 0;
/// Uninitialize the decoder
virtual long EXTAPI Uninitialize() = 0;
/**
* @brief Decode one frame
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param ppDst buffer pointer of decoded data (YUV)
* @param pStride output stride
* @param iWidth output width
* @param iHeight output height
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
int* pStride,
int& iWidth,
int& iHeight) = 0;
/*
* return: 0 - success; otherwise -failed;
*/
/**
* @brief For slice level DecodeFrame2() (4 parameters input),
* whatever the function return value is, the output data
* of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
* (e.g., in multi-slice cases, only when the whole picture
* is completely reconstructed, this variable would be set equal to 1.)
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param ppDst buffer pointer of decoded data (YUV)
* @param pDstInfo information provided to API(width, height, etc.)
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
SBufferInfo* pDstInfo) = 0;
/*
* This function parse input bitstream only, and rewrite possible SVC syntax to AVC syntax
* return: 0 - success; otherwise -failed;
*/
/**
* @brief This function parse input bitstream only, and rewrite possible SVC syntax to AVC syntax
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param pDstInfo bit stream info
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
const int iSrcLen,
SParserBsInfo* pDstInfo) = 0;
/*
* this API does not work for now!! This is for future use to support non-I420 color format output.
*/
/**
* @brief This API does not work for now!! This is for future use to support non-I420 color format output.
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param pDst buffer pointer of decoded data (YUV)
* @param iDstStride output stride
* @param iDstLen bit stream info
* @param iWidth output width
* @param iHeight output height
* @param iColorFormat output color format
* @return to do ...
*/
virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
const int iSrcLen,
unsigned char* pDst,
@@ -126,10 +416,18 @@ class ISVCDecoder {
int& iHeight,
int& iColorFormat) = 0;
/*************************************************************************
* OutDataFormat, Eos Flag, EC method, ...
*************************************************************************/
/**
* @brief Set option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
* @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
/**
* @brief Get option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
* @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
virtual ~ISVCDecoder() {}
};
@@ -197,11 +495,38 @@ long (*GetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
/** @brief Create encoder
* @param ppEncoder encoder
* @return 0 - success; otherwise - failed;
*/
int WelsCreateSVCEncoder (ISVCEncoder** ppEncoder);
/** @brief Destroy encoder
* @param pEncoder encoder
* @return void
*/
void WelsDestroySVCEncoder (ISVCEncoder* pEncoder);
/** @brief Get the capability of decoder
* @param pDecCapability decoder capability
* @return 0 - success; otherwise - failed;
*/
int WelsGetDecoderCapability (SDecoderCapability* pDecCapability);
/** @brief Create decoder
* @param ppDecoder decoder
* @return 0 - success; otherwise - failed;
*/
long WelsCreateDecoder (ISVCDecoder** ppDecoder);
/** @brief Destroy decoder
* @param pDecoder decoder
* @return void
*/
void WelsDestroyDecoder (ISVCDecoder* pDecoder);
#ifdef __cplusplus

View File

@@ -30,9 +30,15 @@
*
*/
#ifndef WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
#define WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
////////////////Data and /or structures introduced in Cisco OpenH264 application////////////////
/**
* @file codec_app_def.h
* @brief Data and /or structures introduced in Cisco OpenH264 application
*/
#include "codec_def.h"
/* Constants */
#define MAX_TEMPORAL_LAYER_NUM 4
@@ -40,114 +46,143 @@
#define MAX_QUALITY_LAYER_NUM 4
#define MAX_LAYER_NUM_OF_FRAME 128
#define MAX_NAL_UNITS_IN_LAYER 128 // predetermined here, adjust it later if need
#define MAX_NAL_UNITS_IN_LAYER 128 ///< predetermined here, adjust it later if need
#define MAX_RTP_PAYLOAD_LEN 1000
#define AVERAGE_RTP_PAYLOAD_LEN 800
#define SAVED_NALUNIT_NUM_TMP ( (MAX_SPATIAL_LAYER_NUM*MAX_QUALITY_LAYER_NUM) + 1 + MAX_SPATIAL_LAYER_NUM ) //SPS/PPS + SEI/SSEI + PADDING_NAL
#define SAVED_NALUNIT_NUM_TMP ( (MAX_SPATIAL_LAYER_NUM*MAX_QUALITY_LAYER_NUM) + 1 + MAX_SPATIAL_LAYER_NUM ) ///< SPS/PPS + SEI/SSEI + PADDING_NAL
#define MAX_SLICES_NUM_TMP ( ( MAX_NAL_UNITS_IN_LAYER - SAVED_NALUNIT_NUM_TMP ) / 3 )
#define AUTO_REF_PIC_COUNT -1 // encoder selects the number of reference frame automatically
typedef enum {
/* Errors derived from bitstream parsing */
dsErrorFree = 0x00, /* Bitstream error-free */
dsFramePending = 0x01, /* Need more throughput to generate a frame output, */
dsRefLost = 0x02, /* layer lost at reference frame with temporal id 0 */
dsBitstreamError = 0x04, /* Error bitstreams(maybe broken internal frame) the decoder cared */
dsDepLayerLost = 0x08, /* Dependented layer is ever lost */
dsNoParamSets = 0x10, /* No parameter set NALs involved */
dsDataErrorConcealed = 0x20, /* current data Error concealed specified */
/* Errors derived from logic level */
dsInvalidArgument = 0x1000, /* Invalid argument specified */
dsInitialOptExpected = 0x2000, /* Initializing operation is expected */
dsOutOfMemory = 0x4000, /* Out of memory due to new request */
/* ANY OTHERS? */
dsDstBufNeedExpand = 0x8000 /* Actual picture size exceeds size of dst pBuffer feed in decoder, so need expand its size */
#define AUTO_REF_PIC_COUNT -1 ///< encoder selects the number of reference frame automatically
#define UNSPECIFIED_BIT_RATE 0 ///< to do: add detail comment
/**
* @brief Decoding status
*/
typedef enum {
/**
* Errors derived from bitstream parsing
*/
dsErrorFree = 0x00, ///< bit stream error-free
dsFramePending = 0x01, ///< need more throughput to generate a frame output,
dsRefLost = 0x02, ///< layer lost at reference frame with temporal id 0
dsBitstreamError = 0x04, ///< error bitstreams(maybe broken internal frame) the decoder cared
dsDepLayerLost = 0x08, ///< dependented layer is ever lost
dsNoParamSets = 0x10, ///< no parameter set NALs involved
dsDataErrorConcealed = 0x20, ///< current data error concealed specified
/**
* Errors derived from logic level
*/
dsInvalidArgument = 0x1000, ///< invalid argument specified
dsInitialOptExpected = 0x2000, ///< initializing operation is expected
dsOutOfMemory = 0x4000, ///< out of memory due to new request
/**
* ANY OTHERS?
*/
dsDstBufNeedExpan = 0x8000 ///< actual picture size exceeds size of dst pBuffer feed in decoder, so need expand its size
} DECODING_STATE;
/* Option types introduced in SVC encoder application */
/**
* @brief Option types introduced in SVC encoder application
*/
typedef enum {
ENCODER_OPTION_DATAFORMAT = 0,
ENCODER_OPTION_IDR_INTERVAL,
ENCODER_OPTION_SVC_ENCODE_PARAM_BASE,
ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
ENCODER_OPTION_FRAME_RATE,
ENCODER_OPTION_IDR_INTERVAL, ///< IDR period,0/-1 means no Intra period (only the first frame); lager than 0 means the desired IDR period, must be multiple of (2^temporal_layer)
ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, ///< structure of Base Param
ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ///< structure of Extension Param
ENCODER_OPTION_FRAME_RATE, ///< maximal input frame rate, current supported range: MAX_FRAME_RATE = 30,MIN_FRAME_RATE = 1
ENCODER_OPTION_BITRATE,
ENCODER_OPTION_MAX_BITRATE,
ENCODER_OPTION_INTER_SPATIAL_PRED,
ENCODER_OPTION_RC_MODE,
ENCODER_PADDING_PADDING,
ENCODER_PADDING_PADDING, ///< 0:disable padding;1:padding
ENCODER_OPTION_PROFILE,
ENCODER_OPTION_LEVEL,
ENCODER_OPTION_NUMBER_REF,
ENCODER_OPTION_DELIVERY_STATUS,
ENCODER_OPTION_PROFILE, ///< assgin the profile for each layer
ENCODER_OPTION_LEVEL, ///< assgin the level for each layer
ENCODER_OPTION_NUMBER_REF, ///< the number of refererence frame
ENCODER_OPTION_DELIVERY_STATUS, ///< the delivery info which is a feedback from app level
ENCODER_LTR_RECOVERY_REQUEST,
ENCODER_LTR_MARKING_FEEDBACK,
ENCODER_LTR_MARKING_PERIOD,
ENCODER_OPTION_LTR,
ENCODER_OPTION_LTR, ///< 0:disable LTR;larger than 0 enable LTR; LTR number is fixed to be 2 in current encoder
ENCODER_OPTION_COMPLEXITY,
ENCODER_OPTION_ENABLE_SSEI, //enable SSEI: true--enable ssei; false--disable ssei
ENCODER_OPTION_ENABLE_PREFIX_NAL_ADDING, //enable prefix: true--enable prefix; false--disable prefix
ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, //enable pSps/pPps id addition: true--enable pSps/pPps id; false--disable pSps/pPps id addistion
ENCODER_OPTION_ENABLE_SSEI, ///< enable SSEI: true--enable ssei; false--disable ssei
ENCODER_OPTION_ENABLE_PREFIX_NAL_ADDING, ///< enable prefix: true--enable prefix; false--disable prefix
ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, ///< enable pSps/pPps id addition: true--enable pSps/pPps id; false--disable pSps/pPps id addistion
ENCODER_OPTION_CURRENT_PATH,
ENCODER_OPTION_DUMP_FILE,
ENCODER_OPTION_TRACE_LEVEL,
ENCODER_OPTION_TRACE_CALLBACK, // a void (*)(void* context, int level, const char* message) function which receives log messages
ENCODER_OPTION_TRACE_CALLBACK_CONTEXT,
ENCODER_OPTION_DUMP_FILE, ///< dump layer reconstruct frame to a specified file
ENCODER_OPTION_TRACE_LEVEL, ///< trace info based on the trace level
ENCODER_OPTION_TRACE_CALLBACK, ///< a void (*)(void* context, int level, const char* message) function which receives log messages
ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, ///< context info of trace callback
ENCODER_OPTION_GET_STATISTICS, //read only
ENCODER_OPTION_STATISTICS_LOG_INTERVAL, // log interval in milliseconds
ENCODER_OPTION_GET_STATISTICS, ///< read only
ENCODER_OPTION_STATISTICS_LOG_INTERVAL, ///< log interval in millisecond
// advanced algorithmetic settings
ENCODER_OPTION_IS_LOSSLESS_LINK
ENCODER_OPTION_IS_LOSSLESS_LINK ///< advanced algorithmetic settings
} ENCODER_OPTION;
/* Option types introduced in decoder application */
/**
* @brief Option types introduced in decoder application
*/
typedef enum {
DECODER_OPTION_DATAFORMAT = 0, /* Set color space of decoding output frame */
DECODER_OPTION_END_OF_STREAM, /* Indicate bitstream of the final frame to be decoded */
DECODER_OPTION_VCL_NAL, //feedback whether or not have VCL NAL in current AU for application layer
DECODER_OPTION_TEMPORAL_ID, //feedback temporal id for application layer
DECODER_OPTION_FRAME_NUM, //feedback current decoded frame number
DECODER_OPTION_IDR_PIC_ID, // feedback current frame belong to which IDR period
DECODER_OPTION_LTR_MARKING_FLAG, // feedback wether current frame mark a LTR
DECODER_OPTION_LTR_MARKED_FRAME_NUM, // feedback frame num marked by current Frame
DECODER_OPTION_ERROR_CON_IDC, //not finished yet, indicate decoder error concealment status, in progress
DECODER_OPTION_DATAFORMAT = 0, ///< color format, now supports 23 only (I420)
DECODER_OPTION_END_OF_STREAM, ///< end of stream flag
DECODER_OPTION_VCL_NAL, ///< feedback whether or not have VCL NAL in current AU for application layer
DECODER_OPTION_TEMPORAL_ID, ///< feedback temporal id for application layer
DECODER_OPTION_FRAME_NUM, ///< feedback current decoded frame number
DECODER_OPTION_IDR_PIC_ID, ///< feedback current frame belong to which IDR period
DECODER_OPTION_LTR_MARKING_FLAG, ///< feedback wether current frame mark a LTR
DECODER_OPTION_LTR_MARKED_FRAME_NUM, ///< feedback frame num marked by current Frame
DECODER_OPTION_ERROR_CON_IDC, ///< not finished yet, indicate decoder error concealment status, in progress
DECODER_OPTION_TRACE_LEVEL,
DECODER_OPTION_TRACE_CALLBACK, // a void (*)(void* context, int level, const char* message) function which receives log messages
DECODER_OPTION_TRACE_CALLBACK_CONTEXT,
DECODER_OPTION_TRACE_CALLBACK, ///< a void (*)(void* context, int level, const char* message) function which receives log messages
DECODER_OPTION_TRACE_CALLBACK_CONTEXT,///< context info of trace callbac
DECODER_OPTION_GET_STATISTICS
} DECODER_OPTION;
//enuerate the types of error concealment methods
/**
* @brief Enumerate the type of error concealment methods
*/
typedef enum {
ERROR_CON_DISABLE = 0,
ERROR_CON_FRAME_COPY,
ERROR_CON_SLICE_COPY
ERROR_CON_SLICE_COPY,
ERROR_CON_FRAME_COPY_CROSS_IDR,
ERROR_CON_SLICE_COPY_CROSS_IDR,
ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE,
ERROR_CON_SLICE_MV_COPY_CROSS_IDR,
ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE
} ERROR_CON_IDC;
typedef enum { //feedback that whether or not have VCL NAL in current AU
/**
* @brief Feedback that whether or not have VCL NAL in current AU
*/
typedef enum {
FEEDBACK_NON_VCL_NAL = 0,
FEEDBACK_VCL_NAL,
FEEDBACK_UNKNOWN_NAL
} FEEDBACK_VCL_NAL_IN_AU;
/* Type of layer being encoded */
/**
* @brief Type of layer being encoded
*/
typedef enum {
NON_VIDEO_CODING_LAYER = 0,
VIDEO_CODING_LAYER = 1
} LAYER_TYPE;
/**
* @brief Spatial layer num
*/
typedef enum {
SPATIAL_LAYER_0 = 0,
SPATIAL_LAYER_1 = 1,
@@ -156,13 +191,18 @@ typedef enum {
SPATIAL_LAYER_ALL = 4
} LAYER_NUM;
//enumerate the type of video bitstream which is provided to decoder
/**
* @brief Enumerate the type of video bitstream which is provided to decoder
*/
typedef enum {
VIDEO_BITSTREAM_AVC = 0,
VIDEO_BITSTREAM_SVC = 1,
VIDEO_BITSTREAM_DEFAULT = VIDEO_BITSTREAM_SVC
} VIDEO_BITSTREAM_TYPE;
/**
* @brief Enumerate the type of key frame request
*/
typedef enum {
NO_RECOVERY_REQUSET = 0,
LTR_RECOVERY_REQUEST = 1,
@@ -172,62 +212,87 @@ typedef enum {
LTR_MARKING_FAILED = 5
} KEY_FRAME_REQUEST_TYPE;
/**
* @brief Structure for LTR recover request
*/
typedef struct {
unsigned int uiFeedbackType; //IDR request or LTR recovery request
unsigned int uiIDRPicId; // distinguish request from different IDR
int iLastCorrectFrameNum;
int iCurrentFrameNum; //specify current decoder frame_num.
unsigned int uiFeedbackType; ///< IDR request or LTR recovery request
unsigned int uiIDRPicId; ///< distinguish request from different IDR
int iLastCorrectFrameNum;
int iCurrentFrameNum; ///< specify current decoder frame_num.
} SLTRRecoverRequest;
/**
* @brief Structure for LTR marking feedback
*/
typedef struct {
unsigned int uiFeedbackType; //mark failed or successful
unsigned int uiIDRPicId; // distinguish request from different IDR
int iLTRFrameNum; //specify current decoder frame_num
unsigned int uiFeedbackType; ///< mark failed or successful
unsigned int uiIDRPicId; ///< distinguish request from different IDR
int iLTRFrameNum; ///< specify current decoder frame_num
} SLTRMarkingFeedback;
/**
* @brief Structure for LTR configuration
*/
typedef struct {
bool bEnableLongTermReference; // 1: on, 0: off
int iLTRRefNum; //TODO: not supported to set it arbitrary yet
bool bEnableLongTermReference; ///< 1: on, 0: off
int iLTRRefNum; ///< TODO: not supported to set it arbitrary yet
} SLTRConfig;
/**
* @brief Structure for slice argument
*/
typedef struct {
unsigned int
uiSliceMbNum[MAX_SLICES_NUM_TMP]; //here we use a tmp fixed value since MAX_SLICES_NUM is not defined here and its definition may be changed;
unsigned int uiSliceNum;
unsigned int uiSliceSizeConstraint;
} SSliceArgument;//not all the elements in this argument will be used, how it will be used depends on uiSliceMode; see below
uiSliceMbNum[MAX_SLICES_NUM_TMP]; ///< only used when uiSliceMode=2;here we use a tmp fixed value since MAX_SLICES_NUM is not defined here and its definition may be changed;
unsigned int uiSliceNum; ///< only used when uiSliceMode=1
unsigned int uiSliceSizeConstraint; ///< only used when uiSliceMode=4
} SSliceArgument; ///< not all the elements in this argument will be used, how it will be used depends on uiSliceMode; please refer to SliceModeEnum
/**
* @brief Enumerate the type of slice mode
*/
typedef enum {
SM_SINGLE_SLICE = 0, // | SliceNum==1
SM_FIXEDSLCNUM_SLICE = 1, // | according to SliceNum | Enabled dynamic slicing for multi-thread
SM_RASTER_SLICE = 2, // | according to SlicesAssign | Need input of MB numbers each slice. In addition, if other constraint in SSliceArgument is presented, need to follow the constraints. Typically if MB num and slice size are both constrained, re-encoding may be involved.
SM_ROWMB_SLICE = 3, // | according to PictureMBHeight | Typical of single row of mbs each slice?+ slice size constraint which including re-encoding
SM_DYN_SLICE = 4, // | according to SliceSize | Dynamic slicing (have no idea about slice_nums until encoding current frame)
SM_AUTO_SLICE = 5, // | according to thread number
SM_SINGLE_SLICE = 0, ///< | SliceNum==1
SM_FIXEDSLCNUM_SLICE = 1, ///< | according to SliceNum | enabled dynamic slicing for multi-thread
SM_RASTER_SLICE = 2, ///< | according to SlicesAssign | need input of MB numbers each slice. In addition, if other constraint in SSliceArgument is presented, need to follow the constraints. Typically if MB num and slice size are both constrained, re-encoding may be involved.
SM_ROWMB_SLICE = 3, ///< | according to PictureMBHeight | typical of single row of mbs each slice + slice size constraint which including re-encoding
SM_DYN_SLICE = 4, ///< | according to SliceSize | dynamic slicing (have no idea about slice_nums until encoding current frame)
SM_AUTO_SLICE = 5, ///< | according to thread number
SM_RESERVED = 6
} SliceModeEnum;
/**
* @brief Enumerate the type of rate control mode
*/
typedef enum {
RC_QUALITY_MODE = 0, //Quality mode
RC_BITRATE_MODE = 1, //Bitrate mode
RC_BUFFERBASED_MODE = 2,//no bitrate control,only using buffer status,adjust the video quality
RC_OFF_MODE = -1 // rate control off mode
RC_QUALITY_MODE = 0, ///< quality mode
RC_BITRATE_MODE = 1, ///< bitrate mode
RC_BUFFERBASED_MODE = 2, ///< no bitrate control,only using buffer status,adjust the video quality
RC_OFF_MODE = -1 ///< rate control off mode
} RC_MODES;
/**
* @brief Enumerate the type of profile id
*/
typedef enum {
PRO_UNKNOWN = 0,
PRO_UNKNOWN = 0,
PRO_BASELINE = 66,
PRO_MAIN = 77,
PRO_EXTENDED = 88,
PRO_HIGH = 100,
PRO_HIGH10 = 110,
PRO_HIGH422 = 122,
PRO_HIGH444 = 144,
PRO_HIGH10 = 110,
PRO_HIGH422 = 122,
PRO_HIGH444 = 144,
PRO_CAVLC444 = 244,
PRO_SCALABLE_BASELINE = 83,
PRO_SCALABLE_HIGH = 86
} EProfileIdc;
/**
* @brief Enumerate the type of level id
*/
typedef enum {
LEVEL_UNKNOWN,
LEVEL_1_0,
@@ -249,136 +314,159 @@ typedef enum {
LEVEL_5_2
} ELevelIdc;
/**
* @brief Enumerate the type of wels log
*/
enum {
WELS_LOG_QUIET = 0x00, // Quiet mode
WELS_LOG_ERROR = 1 << 0, // Error log iLevel
WELS_LOG_WARNING = 1 << 1, // Warning log iLevel
WELS_LOG_INFO = 1 << 2, // Information log iLevel
WELS_LOG_DEBUG = 1 << 3, // Debug log, critical algo log
WELS_LOG_DETAIL = 1 << 4, // per packet/frame log
WELS_LOG_RESV = 1 << 5, // Resversed log iLevel
WELS_LOG_QUIET = 0x00, ///< quiet mode
WELS_LOG_ERROR = 1 << 0, ///< error log iLevel
WELS_LOG_WARNING = 1 << 1, ///< Warning log iLevel
WELS_LOG_INFO = 1 << 2, ///< information log iLevel
WELS_LOG_DEBUG = 1 << 3, ///< debug log, critical algo log
WELS_LOG_DETAIL = 1 << 4, ///< per packet/frame log
WELS_LOG_RESV = 1 << 5, ///< resversed log iLevel
WELS_LOG_LEVEL_COUNT = 6,
WELS_LOG_DEFAULT = WELS_LOG_DEBUG // Default log iLevel in Wels codec
WELS_LOG_DEFAULT = WELS_LOG_DEBUG ///< default log iLevel in Wels codec
};
/**
* @brief Structure for slice configuration
*/
typedef struct {
SliceModeEnum uiSliceMode; //by default, uiSliceMode will be SM_SINGLE_SLICE
SliceModeEnum uiSliceMode; ///< by default, uiSliceMode will be SM_SINGLE_SLICE
SSliceArgument sSliceArgument;
} SSliceConfig;
/**
* @brief Structure for spatial layer configuration
*/
typedef struct {
int iVideoWidth; // video size in cx specified for a layer
int iVideoHeight; // video size in cy specified for a layer
float fFrameRate; // frame rate specified for a layer
int iSpatialBitrate; // target bitrate for a spatial layer
int iMaxSpatialBitrate;
EProfileIdc uiProfileIdc; // value of profile IDC (PRO_UNKNOWN for auto-detection)
ELevelIdc uiLevelIdc;
int iDLayerQp;
int iVideoWidth; ///< width of picture in luminance samples of a layer
int iVideoHeight; ///< height of picture in luminance samples of a layer
float fFrameRate; ///< frame rate specified for a layer
int iSpatialBitrate; ///< target bitrate for a spatial layer
int iMaxSpatialBitrate; ///< maximum bitrate for a spatial layer
EProfileIdc uiProfileIdc; ///< value of profile IDC (PRO_UNKNOWN for auto-detection)
ELevelIdc uiLevelIdc; ///< value of profile IDC (0 for auto-detection)
int iDLayerQp; ///< value of level IDC (0 for auto-detection)
SSliceConfig sSliceCfg;
SSliceConfig sSliceCfg; ///< slice configuration for a layer
} SSpatialLayerConfig;
/**
* @brief Encoder usage type
*/
typedef enum {
CAMERA_VIDEO_REAL_TIME, //camera video signal
SCREEN_CONTENT_REAL_TIME //screen content signal
CAMERA_VIDEO_REAL_TIME, ///< camera video signal
SCREEN_CONTENT_REAL_TIME ///< screen content signal
} EUsageType;
/**
* @brief Enumulate the complexity mode
*/
typedef enum {
LOW_COMPLEXITY, //the lowest compleixty,the fastest speed,
MEDIUM_COMPLEXITY, //medium complexity, medium speed,medium quality
HIGH_COMPLEXITY //high complexity, lowest speed, high quality
LOW_COMPLEXITY, ///< the lowest compleixty,the fastest speed,
MEDIUM_COMPLEXITY, ///< medium complexity, medium speed,medium quality
HIGH_COMPLEXITY ///< high complexity, lowest speed, high quality
} ECOMPLEXITY_MODE;
// TODO: Refine the parameters definition.
// SVC Encoding Parameters
/**
* @brief SVC Encoding Parameters
*/
typedef struct TagEncParamBase {
EUsageType
iUsageType; //application type;// CAMERA_VIDEO_REAL_TIME: //camera video signal; SCREEN_CONTENT_REAL_TIME: screen content signal;
iUsageType; ///< application type;1.CAMERA_VIDEO_REAL_TIME:camera video signal; 2.SCREEN_CONTENT_REAL_TIME:screen content signal;
int iPicWidth; // width of picture in samples
int iPicHeight; // height of picture in samples
int iTargetBitrate; // target bitrate desired
RC_MODES iRCMode; // RC mode
float fMaxFrameRate; // input maximal frame rate
int iPicWidth; ///< width of picture in luminance samples (the maximum of all layers if multiple spatial layers presents)
int iPicHeight; ///< height of picture in luminance samples((the maximum of all layers if multiple spatial layers presents)
int iTargetBitrate; ///< target bitrate desired
RC_MODES iRCMode; ///< rate control mode
float fMaxFrameRate; ///< maximal input frame rate
} SEncParamBase, *PEncParamBase;
/**
* @brief SVC Encoding Parameters extention
*/
typedef struct TagEncParamExt {
EUsageType
iUsageType; //application type;// CAMERA_VIDEO_REAL_TIME: //camera video signal; SCREEN_CONTENT_REAL_TIME: screen content signal;
iUsageType; ///< application type;1.CAMERA_VIDEO_REAL_TIME:camera video signal;2.SCREEN_CONTENT_REAL_TIME:screen content signal;
int iPicWidth; // width of picture in samples
int iPicHeight; // height of picture in samples
int iTargetBitrate; // target bitrate desired
RC_MODES iRCMode; // RC mode
float fMaxFrameRate; // input maximal frame rate
int iPicWidth; ///< width of picture in luminance samples (the maximum of all layers if multiple spatial layers presents)
int iPicHeight; ///< height of picture in luminance samples((the maximum of all layers if multiple spatial layers presents)
int iTargetBitrate; ///< target bitrate desired
RC_MODES iRCMode; ///< rate control mode
float fMaxFrameRate; ///< maximal input frame rate
int iTemporalLayerNum; // layer number at temporal level
int iSpatialLayerNum; // layer number at spatial level
int iTemporalLayerNum; ///< temporal layer number, max temporal layer = 4
int iSpatialLayerNum; ///< spatial layer number,1<= iSpatialLayerNum <= MAX_SPATIAL_LAYER_NUM, MAX_SPATIAL_LAYER_NUM = 4
SSpatialLayerConfig sSpatialLayers[MAX_SPATIAL_LAYER_NUM];
ECOMPLEXITY_MODE iComplexityMode;
unsigned int uiIntraPeriod; // period of Intra frame
int iNumRefFrame; // number of reference frame used
bool bEnableSpsPpsIdAddition;
bool bPrefixNalAddingCtrl;
bool bEnableSSEI;
int iPaddingFlag; // 0:disable padding;1:padding
int iEntropyCodingModeFlag;
unsigned int uiIntraPeriod; ///< period of Intra frame
int iNumRefFrame; ///< number of reference frame used
bool bEnableSpsPpsIdAddition; ///< false:not adjust ID in SPS/PPS; true: adjust ID in SPS/PPS
bool bPrefixNalAddingCtrl; ///< false:not use Prefix NAL; true: use Prefix NAL
bool bEnableSSEI; ///< false:not use SSEI; true: use SSEI
int iPaddingFlag; ///< 0:disable padding;1:padding
int iEntropyCodingModeFlag; ///< 0:CAVLC 1:CABAC.
/* rc control */
bool bEnableFrameSkip; // allow skipping frames to keep the bitrate within limits
int iMaxBitrate; // max bitrate desired
int iMaxQp;
int iMinQp;
unsigned int uiMaxNalSize;
bool bEnableFrameSkip; ///< False: don't skip frame even if VBV buffer overflow.True: allow skipping frames to keep the bitrate within limits
int iMaxBitrate; ///< the maximum bitrate
int iMaxQp; ///< the maximum QP encoder supports
int iMinQp; ///< the minmum QP encoder supports
unsigned int uiMaxNalSize; ///< the maximum NAL size. This value should be not 0 for dynamic slice mode
/*LTR settings*/
bool bEnableLongTermReference; // 1: on, 0: off
int iLTRRefNum; //TODO: not supported to set it arbitrary yet
unsigned int iLtrMarkPeriod;
bool bEnableLongTermReference; ///< 1: on, 0: off
int iLTRRefNum; ///< the number of LTR(long term reference),TODO: not supported to set it arbitrary yet
unsigned int iLtrMarkPeriod; ///< the LTR marked period that is used in feedback.
/* multi-thread settings*/
unsigned short
iMultipleThreadIdc; // 1 # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads;
iMultipleThreadIdc; ///< 1 # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; lager than 1: count number of threads;
/* Deblocking loop filter */
int iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries
int iLoopFilterAlphaC0Offset;// AlphaOffset: valid range [-6, 6], default 0
int iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0
int iLoopFilterDisableIdc; ///< 0: on, 1: off, 2: on except for slice boundaries
int iLoopFilterAlphaC0Offset; ///< AlphaOffset: valid range [-6, 6], default 0
int iLoopFilterBetaOffset; ///< BetaOffset: valid range [-6, 6], default 0
/*pre-processing feature*/
bool bEnableDenoise; // denoise control
bool bEnableBackgroundDetection;// background detection control //VAA_BACKGROUND_DETECTION //BGD cmd
bool bEnableAdaptiveQuant; // adaptive quantization control
bool bEnableFrameCroppingFlag;// enable frame cropping flag: TRUE always in application
bool bEnableDenoise; ///< denoise control
bool bEnableBackgroundDetection; ///< background detection control //VAA_BACKGROUND_DETECTION //BGD cmd
bool bEnableAdaptiveQuant; ///< adaptive quantization control
bool bEnableFrameCroppingFlag; ///< enable frame cropping flag: TRUE always in application
bool bEnableSceneChangeDetect;
/*LTR advanced setting*/
bool bIsLosslessLink;
bool bIsLosslessLink; ///< LTR advanced setting
} SEncParamExt;
//Define a new struct to show the property of video bitstream.
/**
* @brief Define a new struct to show the property of video bitstream.
*/
typedef struct {
unsigned int size; //size of the struct
VIDEO_BITSTREAM_TYPE eVideoBsType;
unsigned int size; ///< size of the struct
VIDEO_BITSTREAM_TYPE eVideoBsType; ///< video stream type (AVC/SVC)
} SVideoProperty;
/* SVC Decoding Parameters, reserved here and potential applicable in the future */
/**
* @brief SVC Decoding Parameters, reserved here and potential applicable in the future
*/
typedef struct TagSVCDecodingParam {
char* pFileNameRestructed; // File name of restructed frame used for PSNR calculation based debug
char* pFileNameRestructed; ///< file name of reconstructed frame used for PSNR calculation based debug
EVideoFormatType eOutputColorFormat; // color space format to be outputed, EVideoFormatType specified in codec_def.h
unsigned int uiCpuLoad; // CPU load
unsigned char uiTargetDqLayer; // Setting target dq layer id
EVideoFormatType eOutputColorFormat; ///< color space format to be outputed, EVideoFormatType specified in codec_def.h
unsigned int uiCpuLoad; ///< CPU load
unsigned char uiTargetDqLayer; ///< setting target dq layer id
ERROR_CON_IDC eEcActiveIdc; // Whether active error concealment feature in decoder
ERROR_CON_IDC eEcActiveIdc; ///< whether active error concealment feature in decoder
bool bParseOnly; ///< decoder for parse only, no reconstruction. When it is true, SPS/PPS size should not exceed SPS_PPS_BS_SIZE (128). Otherwise, it will return error info
SVideoProperty sVideoProperty;
SVideoProperty sVideoProperty; ///< video stream property
} SDecodingParam, *PDecodingParam;
/* Bitstream inforamtion of a layer being encoded */
/**
* @brief Bitstream inforamtion of a layer being encoded
*/
typedef struct {
unsigned char uiTemporalId;
unsigned char uiSpatialId;
@@ -386,112 +474,152 @@ typedef struct {
unsigned char uiLayerType;
int iNalCount; // Count number of NAL coded already
int* pNalLengthInByte; // Length of NAL size in byte from 0 to iNalCount-1
unsigned char* pBsBuf; // Buffer of bitstream contained
int iNalCount; ///< count number of NAL coded already
int* pNalLengthInByte; ///< length of NAL size in byte from 0 to iNalCount-1
unsigned char* pBsBuf; ///< buffer of bitstream contained
} SLayerBSInfo, *PLayerBSInfo;
/**
* @brief Frame bit stream info
*/
typedef struct {
int iTemporalId; // Temporal ID
//The sub sequence layers are ordered hierarchically based on their dependency on each other so that any picture in a layer shall not be
//predicted from any picture on any higher layer.
int iSubSeqId; //refer to D.2.11 Sub-sequence information SEI message semantics
int iTemporalId; ///< temporal ID
/**
* The sub sequence layers are ordered hierarchically based on their dependency on each other so that any picture in a layer shall not be
* predicted from any picture on any higher layer.
*/
int iSubSeqId; ///< refer to D.2.11 Sub-sequence information SEI message semantics
int iLayerNum;
SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
EVideoFrameType eFrameType;
int iFrameSizeInBytes;
long long uiTimeStamp;
} SFrameBSInfo, *PFrameBSInfo;
/**
* @brief Structure for source picture
*/
typedef struct Source_Picture_s {
int iColorFormat; // color space type
int iStride[4]; // stride for each plane pData
unsigned char* pData[4]; // plane pData
int iPicWidth; // luma picture width in x coordinate
int iPicHeight; // luma picture height in y coordinate
int iColorFormat; ///< color space type
int iStride[4]; ///< stride for each plane pData
unsigned char* pData[4]; ///< plane pData
int iPicWidth; ///< luma picture width in x coordinate
int iPicHeight; ///< luma picture height in y coordinate
long long uiTimeStamp;
} SSourcePicture;
/**
* @brief Structure for bit rate info
*/
typedef struct TagBitrateInfo {
LAYER_NUM iLayer;
int iBitrate; //the maximum bitrate
int iBitrate; ///< the maximum bitrate
} SBitrateInfo;
/**
* @brief Structure for dump layer info
*/
typedef struct TagDumpLayer {
int iLayer;
char* pFileName;
} SDumpLayer;
/**
* @brief Structure for profile info in layer
*
*/
typedef struct TagProfileInfo {
int iLayer;
EProfileIdc uiProfileIdc; //the profile info
EProfileIdc uiProfileIdc; ///< the profile info
} SProfileInfo;
/**
* @brief Structure for level info in layer
*
*/
typedef struct TagLevelInfo {
int iLayer;
ELevelIdc uiLevelIdc; //the level info
ELevelIdc uiLevelIdc; ///< the level info
} SLevelInfo;
/**
* @brief Structure for dilivery status
*
*/
typedef struct TagDeliveryStatus {
bool bDeliveryFlag; //0: the previous frame isn't delivered,1: the previous frame is delivered
int iDropFrameType; // the frame type that is dropped; reserved
int iDropFrameSize; // the frame size that is dropped; reserved
bool bDeliveryFlag; ///< 0: the previous frame isn't delivered,1: the previous frame is delivered
int iDropFrameType; ///< the frame type that is dropped; reserved
int iDropFrameSize; ///< the frame size that is dropped; reserved
} SDeliveryStatus;
/**
* @brief The capability of decoder, for SDP negotiation
*/
typedef struct TagDecoderCapability {
int iProfileIdc;
int iProfileIop;
int iLevelIdc;
int iMaxMbps;
int iMaxFs;
int iMaxCpb;
int iMaxDpb;
int iMaxBr;
bool bRedPicCap;
int iProfileIdc; ///< profile_idc
int iProfileIop; ///< profile-iop
int iLevelIdc; ///< level_idc
int iMaxMbps; ///< max-mbps
int iMaxFs; ///< max-fs
int iMaxCpb; ///< max-cpb
int iMaxDpb; ///< max-dpb
int iMaxBr; ///< max-br
bool bRedPicCap; ///< redundant-pic-cap
} SDecoderCapability;
/**
* @brief to do
*/
typedef struct TagParserBsInfo {
int iNalNum; //total NAL number in current AU
int iNalLenInByte [MAX_NAL_UNITS_IN_LAYER]; //each nal length
unsigned char* pDstBuff; //outputted dst buffer for parsed bitstream
int iSpsWidthInPixel; //required SPS width info
int iSpsHeightInPixel; //required SPS height info
} SParserBsInfo, PParserBsInfo;
int iNalNum; ///< total NAL number in current AU
int iNalLenInByte [MAX_NAL_UNITS_IN_LAYER]; ///< each nal length
unsigned char* pDstBuff; ///< outputted dst buffer for parsed bitstream
int iSpsWidthInPixel; ///< required SPS width info
int iSpsHeightInPixel; ///< required SPS height info
unsigned long long uiInBsTimeStamp; ///< input BS timestamp
unsigned long long uiOutBsTimeStamp; ///< output BS timestamp
} SParserBsInfo, *PParserBsInfo;
/**
* @brief Structure for encoder statistics
*/
typedef struct TagVideoEncoderStatistics {
unsigned int uiWidth; // the width of encoded frame
unsigned int uiHeight; // the height of encoded frame
unsigned int uiWidth; ///< the width of encoded frame
unsigned int uiHeight; ///< the height of encoded frame
//following standard, will be 16x aligned, if there are multiple spatial, this is of the highest
float fAverageFrameSpeedInMs; // Average_Encoding_Time
float fAverageFrameSpeedInMs; ///< average_Encoding_Time
// rate control related
float fAverageFrameRate; // the average frame rate in, calculate since encoding starts, supposed that the input timestamp is in unit of ms
float fLatestFrameRate; // the frame rate in, in the last second, supposed that the input timestamp is in unit of ms (? useful for checking BR, but is it easy to calculate?
unsigned int uiBitRate; // sendrate in Bits per second, calculated within the set time-window
float fAverageFrameRate; ///< the average frame rate in, calculate since encoding starts, supposed that the input timestamp is in unit of ms
float fLatestFrameRate; ///< the frame rate in, in the last second, supposed that the input timestamp is in unit of ms (? useful for checking BR, but is it easy to calculate?
unsigned int uiBitRate; ///< sendrate in Bits per second, calculated within the set time-window
unsigned int uiInputFrameCount; // number of frames
unsigned int uiSkippedFrameCount; // number of frames
unsigned int uiInputFrameCount; ///< number of frames
unsigned int uiSkippedFrameCount; ///< number of frames
unsigned int uiResolutionChangeTimes; // uiResolutionChangeTimes
unsigned int uiIDRReqNum; // number of IDR requests
unsigned int uiIDRSentNum; // number of actual IDRs sent
unsigned int uiLTRSentNum; // number of LTR sent/marked
unsigned int uiResolutionChangeTimes; ///< uiResolutionChangeTimes
unsigned int uiIDRReqNum; ///< number of IDR requests
unsigned int uiIDRSentNum; ///< number of actual IDRs sent
unsigned int uiLTRSentNum; ///< number of LTR sent/marked
} SEncoderStatistics; // in building, coming soon
/**
* @brief Structure for decoder statistics
*/
typedef struct TagVideoDecoderStatistics {
unsigned int uiWidth; // the width of encode/decode frame
unsigned int uiHeight; // the height of encode/decode frame
float fAverageFrameSpeedInMs; // Average_Decoding_Time
unsigned int uiDecodedFrameCount; // number of frames
unsigned int uiResolutionChangeTimes; // uiResolutionChangeTimes
unsigned int uiWidth; ///< the width of encode/decode frame
unsigned int uiHeight; ///< the height of encode/decode frame
float fAverageFrameSpeedInMs; ///< average_Decoding_Time
unsigned int uiDecodedFrameCount; ///< number of frames
unsigned int uiResolutionChangeTimes; ///< uiResolutionChangeTimes
unsigned int uiIDRRecvNum; ///< number of actual IDR received
//EC on related
unsigned int
uiAvgEcRatio; // when EC is on, the average ratio of correct or EC areas, can be an indicator of reconstruction quality
unsigned int uiIDRReqNum; // number of actual IDR request
unsigned int uiLTRReqNum; // number of actual LTR request
unsigned int uiIDRRecvNum; // number of actual IDR received
uiAvgEcRatio; ///< when EC is on, the average ratio of correct or EC areas, can be an indicator of reconstruction quality
unsigned int uiEcIDRNum; ///< number of actual unintegrity IDR or not received but eced
unsigned int uiEcFrameNum; ///<
unsigned int uiIDRLostNum; ///< decoder detect the number of lost IDR
} SDecoderStatistics; // in building, coming soon
#endif//WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__

View File

@@ -33,9 +33,15 @@
#ifndef WELS_VIDEO_CODEC_DEFINITION_H__
#define WELS_VIDEO_CODEC_DEFINITION_H__
/**
* @file codec_def.h
*/
/**
* @brief Enumerate the type of video format
*/
typedef enum {
/*rgb color formats*/
videoFormatRGB = 1,
videoFormatRGB = 1, ///< rgb color formats
videoFormatRGBA = 2,
videoFormatRGB555 = 3,
videoFormatRGB565 = 4,
@@ -44,51 +50,61 @@ typedef enum {
videoFormatABGR = 7,
videoFormatARGB = 8,
/*yuv color formats*/
videoFormatYUY2 = 20,
videoFormatYUY2 = 20, ///< yuv color formats
videoFormatYVYU = 21,
videoFormatUYVY = 22,
videoFormatI420 = 23, //same as IYUV
videoFormatI420 = 23, ///< the same as IYUV
videoFormatYV12 = 24,
videoFormatInternal = 25, // Only Used for SVC decoder testbed
videoFormatInternal = 25, ///< only used in SVC decoder testbed
videoFormatNV12 = 26, // new format for output by DXVA decoding
videoFormatNV12 = 26, ///< new format for output by DXVA decoding
videoFormatVFlip = 0x80000000
} EVideoFormatType;
/**
* @brief Enumerate video frame type
*/
typedef enum {
videoFrameTypeInvalid, /* Encoder not ready or parameters are invalidate */
videoFrameTypeIDR, /* This type is only available for H264 if this frame is key frame, then return this type */
videoFrameTypeI, /* I frame type */
videoFrameTypeP, /* P frame type */
videoFrameTypeSkip, /* Skip the frame based encoder kernel */
videoFrameTypeIPMixed /* Frame type introduced I and P slices are mixing */
videoFrameTypeInvalid, ///< encoder not ready or parameters are invalidate
videoFrameTypeIDR, ///< IDR frame in H.264
videoFrameTypeI, ///< I frame type
videoFrameTypeP, ///< P frame type
videoFrameTypeSkip, ///< skip the frame based encoder kernel
videoFrameTypeIPMixed ///< a frame where I and P slices are mixing, not supported yet
} EVideoFrameType;
/**
* @brief Enumerate return type
*/
typedef enum {
cmResultSuccess,
cmInitParaError, /*Parameters are invalid */
cmResultSuccess, ///< successful
cmInitParaError, ///< parameters are invalid
cmUnkonwReason,
cmMallocMemeError, /*Malloc a memory error*/
cmInitExpected, /*Initial action is expected*/
cmMallocMemeError, ///< malloc a memory error
cmInitExpected, ///< initial action is expected
cmUnsupportedData
} CM_RETURN;
/* nal unit type */
/**
* @brief Enumulate the nal unit type
*/
enum ENalUnitType {
NAL_UNKNOWN = 0,
NAL_SLICE = 1,
NAL_UNKNOWN = 0,
NAL_SLICE = 1,
NAL_SLICE_DPA = 2,
NAL_SLICE_DPB = 3,
NAL_SLICE_DPC = 4,
NAL_SLICE_IDR = 5, /* ref_idc != 0 */
NAL_SEI = 6, /* ref_idc == 0 */
NAL_SLICE_IDR = 5, ///< ref_idc != 0
NAL_SEI = 6, ///< ref_idc == 0
NAL_SPS = 7,
NAL_PPS = 8
/* ref_idc == 0 for 6,9,10,11,12 */
///< ref_idc == 0 for 6,9,10,11,12
};
/* NRI: eNalRefIdc */
/**
* @brief NRI: eNalRefIdc
*/
enum ENalPriority {
NAL_PRIORITY_DISPOSABLE = 0,
NAL_PRIORITY_LOW = 1,
@@ -107,82 +123,80 @@ enum ENalPriority {
/* Error Tools definition */
typedef unsigned short ERR_TOOL;
/**
@brief to do
*/
enum {
ET_NONE = 0x00, // NONE Error Tools
ET_IP_SCALE = 0x01, // IP Scalable
ET_FMO = 0x02, // Flexible Macroblock Ordering
ET_IR_R1 = 0x04, // Intra Refresh in predifined 2% MB
ET_IR_R2 = 0x08, // Intra Refresh in predifined 5% MB
ET_IR_R3 = 0x10, // Intra Refresh in predifined 10% MB
ET_FEC_HALF = 0x20, // Forward Error Correction in 50% redundency mode
ET_FEC_FULL = 0x40, // Forward Error Correction in 100% redundency mode
ET_RFS = 0x80 // Reference Frame Selection
ET_NONE = 0x00, ///< NONE Error Tools
ET_IP_SCALE = 0x01, ///< IP Scalable
ET_FMO = 0x02, ///< Flexible Macroblock Ordering
ET_IR_R1 = 0x04, ///< Intra Refresh in predifined 2% MB
ET_IR_R2 = 0x08, ///< Intra Refresh in predifined 5% MB
ET_IR_R3 = 0x10, ///< Intra Refresh in predifined 10% MB
ET_FEC_HALF = 0x20, ///< Forward Error Correction in 50% redundency mode
ET_FEC_FULL = 0x40, ///< Forward Error Correction in 100% redundency mode
ET_RFS = 0x80 ///< Reference Frame Selection
};
/* information of coded Slice(=NAL)(s) */
/**
* @brief Information of coded Slice(=NAL)(s)
*/
typedef struct SliceInformation {
unsigned char* pBufferOfSlices; // base buffer of coded slice(s)
int iCodedSliceCount; // number of coded slices
unsigned int* pLengthOfSlices; // array of slices length accordingly by number of slice
int iFecType; // FEC type[0, 50%FEC, 100%FEC]
unsigned char uiSliceIdx; // index of slice in frame [FMO: 0,..,uiSliceCount-1; No FMO: 0]
unsigned char uiSliceCount; // count number of slice in frame [FMO: 2-8; No FMO: 1]
char iFrameIndex; // index of frame[-1, .., idr_interval-1]
unsigned char uiNalRefIdc; // NRI, priority level of slice(NAL)
unsigned char uiNalType; // NAL type
unsigned char* pBufferOfSlices; ///< base buffer of coded slice(s)
int iCodedSliceCount; ///< number of coded slices
unsigned int* pLengthOfSlices; ///< array of slices length accordingly by number of slice
int iFecType; ///< FEC type[0, 50%FEC, 100%FEC]
unsigned char uiSliceIdx; ///< index of slice in frame [FMO: 0,..,uiSliceCount-1; No FMO: 0]
unsigned char uiSliceCount; ///< count number of slice in frame [FMO: 2-8; No FMO: 1]
char iFrameIndex; ///< index of frame[-1, .., idr_interval-1]
unsigned char uiNalRefIdc; ///< NRI, priority level of slice(NAL)
unsigned char uiNalType; ///< NAL type
unsigned char
uiContainingFinalNal; // whether final NAL is involved in buffer of coded slices, flag used in Pause feature in T27
uiContainingFinalNal; ///< whether final NAL is involved in buffer of coded slices, flag used in Pause feature in T27
} SliceInfo, *PSliceInfo;
#define CIF_WIDTH 352
#define CIF_HEIGHT 288
#define QVGA_WIDTH 320
#define QVGA_HEIGHT 240
#define QCIF_WIDTH 176
#define QCIF_HEIGHT 144
#define SQCIF_WIDTH 128
#define SQCIF_HEIGHT 96
/* thresholds of the initial, maximal and minimal rate */
/**
* @brief thresholds of the initial, maximal and minimal rate
*/
typedef struct {
int iWidth; // frame width
int iHeight; // frame height
int iThresholdOfInitRate; // threshold of initial rate
int iThresholdOfMaxRate; // threshold of maximal rate
int iThresholdOfMinRate; // threshold of minimal rate
int iMinThresholdFrameRate; //min frame rate min
int iSkipFrameRate; //skip to frame rate min
int iSkipFrameStep; //how many frames to skip
int iWidth; ///< frame width
int iHeight; ///< frame height
int iThresholdOfInitRate; ///< threshold of initial rate
int iThresholdOfMaxRate; ///< threshold of maximal rate
int iThresholdOfMinRate; ///< threshold of minimal rate
int iMinThresholdFrameRate; ///< min frame rate min
int iSkipFrameRate; ///< skip to frame rate min
int iSkipFrameStep; ///< how many frames to skip
} SRateThresholds, *PRateThresholds;
/**
* @brief Structure for decoder memery
*/
typedef struct TagSysMemBuffer {
int iWidth; //width of decoded pic for display
int iHeight; //height of decoded pic for display
int iFormat; // type is "EVideoFormatType"
int iStride[2]; //stride of 2 component
int iWidth; ///< width of decoded pic for display
int iHeight; ///< height of decoded pic for display
int iFormat; ///< type is "EVideoFormatType"
int iStride[2]; ///< stride of 2 component
} SSysMEMBuffer;
/**
* @brief Buffer info
*/
typedef struct TagBufferInfo {
int iBufferStatus; // 0: one frame data is not ready; 1: one frame data is ready
int iBufferStatus; ///< 0: one frame data is not ready; 1: one frame data is ready
unsigned long long uiInBsTimeStamp; ///< input BS timestamp
unsigned long long uiOutYuvTimeStamp; ///< output YUV timestamp, when bufferstatus is 1
union {
SSysMEMBuffer sSystemBuffer;
} UsrData;
SSysMEMBuffer sSystemBuffer; ///< memory info for one picture
} UsrData; ///< output buffer info
} SBufferInfo;
/* Constants related to transmission rate at various resolutions */
static const SRateThresholds ksRateThrMap[4] = {
// initial-maximal-minimal
{CIF_WIDTH, CIF_HEIGHT, 225000, 384000, 96000, 3, 1, 1}, // CIF
{QVGA_WIDTH, QVGA_HEIGHT, 192000, 320000, 80000, -1, -1, -1}, // QVGA
{QCIF_WIDTH, QCIF_HEIGHT, 150000, 256000, 64000, 8, 4, 2}, // QCIF
{SQCIF_WIDTH, SQCIF_HEIGHT, 120000, 192000, 48000, 5, 3, 1} // SQCIF
};
// In a GOP, multiple of the key frame number, derived from
// the number of layers(index or array below)
/**
* @brief In a GOP, multiple of the key frame number, derived from
* the number of layers(index or array below)
*/
static const char kiKeyNumMultiple[] = {
1, 1, 2, 4, 8, 16,
};

View File

@@ -30,6 +30,8 @@
4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */; };
4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A718BC6BE90017DF25 /* block_add_neon.S */; };
4CE447AE18BC6BE90017DF25 /* intra_pred_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */; };
6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */; };
6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */; };
6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */; };
9ABF4382193EB60900A6BD61 /* expand_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9ABF4381193EB60900A6BD61 /* expand_pic.cpp */; };
9AED66561946A1DE009A3567 /* welsCodecTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AED66551946A1DE009A3567 /* welsCodecTrace.cpp */; };
@@ -109,6 +111,10 @@
4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = welsDecoderExt.cpp; sourceTree = "<group>"; };
4CE447A718BC6BE90017DF25 /* block_add_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = block_add_neon.S; sourceTree = "<group>"; };
4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = intra_pred_neon.S; sourceTree = "<group>"; };
6A3E814019D79AD900C19C1F /* cabac_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cabac_decoder.h; sourceTree = "<group>"; };
6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cabac_decoder.cpp; sourceTree = "<group>"; };
6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_mb_syn_cabac.cpp; sourceTree = "<group>"; };
6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_mb_syn_cabac.h; sourceTree = "<group>"; };
6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = block_add_aarch64_neon.S; path = arm64/block_add_aarch64_neon.S; sourceTree = "<group>"; };
9ABF4380193EB5F700A6BD61 /* expand_pic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = expand_pic.h; path = ../../../common/inc/expand_pic.h; sourceTree = "<group>"; };
9ABF4381193EB60900A6BD61 /* expand_pic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = expand_pic.cpp; path = ../../../common/src/expand_pic.cpp; sourceTree = "<group>"; };
@@ -191,6 +197,8 @@
4CE4464418BC5EAA0017DF25 /* inc */ = {
isa = PBXGroup;
children = (
6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */,
6A3E814019D79AD900C19C1F /* cabac_decoder.h */,
9AED665A1946A21D009A3567 /* utils.h */,
9ABF4380193EB5F700A6BD61 /* expand_pic.h */,
F0B204FA18FD23CF005DA23F /* error_concealment.h */,
@@ -232,6 +240,8 @@
4CE4466618BC5EAA0017DF25 /* src */ = {
isa = PBXGroup;
children = (
6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */,
6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */,
9AED66581946A203009A3567 /* utils.cpp */,
9ABF4381193EB60900A6BD61 /* expand_pic.cpp */,
F0B204FB18FD23D8005DA23F /* error_concealment.cpp */,
@@ -346,6 +356,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */,
4CE4469B18BC5EAB0017DF25 /* pic_queue.cpp in Sources */,
4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */,
4CE4469318BC5EAB0017DF25 /* fmo.cpp in Sources */,
@@ -355,6 +366,7 @@
4CE4469518BC5EAB0017DF25 /* manage_dec_ref.cpp in Sources */,
4CE4468A18BC5EAB0017DF25 /* au_parser.cpp in Sources */,
4CE4469918BC5EAB0017DF25 /* mv_pred.cpp in Sources */,
6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */,
4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */,
6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */,
4CE4469418BC5EAB0017DF25 /* get_intra_predictor.cpp in Sources */,

View File

@@ -51,6 +51,8 @@
9AED66661946A2B3009A3567 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AED66651946A2B3009A3567 /* utils.cpp */; };
F5617A50196A833A006E2B20 /* reconstruct_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = F5617A4F196A833A006E2B20 /* reconstruct_aarch64_neon.S */; };
F5BE8005196B913200ED02ED /* memory_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = F5BE8004196B913200ED02ED /* memory_aarch64_neon.S */; };
F7E9994519EBD1E9009B1021 /* svc_set_mb_syn_cabac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F7E9994419EBD1E9009B1021 /* svc_set_mb_syn_cabac.cpp */; };
F7E9994919EBD1F8009B1021 /* set_mb_syn_cabac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F7E9994819EBD1F8009B1021 /* set_mb_syn_cabac.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -164,6 +166,10 @@
9AED66671946A2C4009A3567 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = ../../../common/inc/utils.h; sourceTree = "<group>"; };
F5617A4F196A833A006E2B20 /* reconstruct_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = reconstruct_aarch64_neon.S; path = arm64/reconstruct_aarch64_neon.S; sourceTree = "<group>"; };
F5BE8004196B913200ED02ED /* memory_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = memory_aarch64_neon.S; path = arm64/memory_aarch64_neon.S; sourceTree = "<group>"; };
F7E9994419EBD1E9009B1021 /* svc_set_mb_syn_cabac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = svc_set_mb_syn_cabac.cpp; sourceTree = "<group>"; };
F7E9994819EBD1F8009B1021 /* set_mb_syn_cabac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = set_mb_syn_cabac.cpp; sourceTree = "<group>"; };
F7E9997E19EBD3C6009B1021 /* set_mb_syn_cabac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = set_mb_syn_cabac.h; sourceTree = "<group>"; };
F7E9997F19EBD3CE009B1021 /* svc_set_mb_syn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svc_set_mb_syn.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -254,6 +260,8 @@
4CE446A918BC605C0017DF25 /* inc */ = {
isa = PBXGroup;
children = (
F7E9997F19EBD3CE009B1021 /* svc_set_mb_syn.h */,
F7E9997E19EBD3C6009B1021 /* set_mb_syn_cabac.h */,
9AED66671946A2C4009A3567 /* utils.h */,
4CDBFB9D18E5068D0025A767 /* wels_transpose_matrix.h */,
4CE446AA18BC605C0017DF25 /* as264_common.h */,
@@ -309,6 +317,8 @@
4CE446DC18BC605C0017DF25 /* src */ = {
isa = PBXGroup;
children = (
F7E9994819EBD1F8009B1021 /* set_mb_syn_cabac.cpp */,
F7E9994419EBD1E9009B1021 /* svc_set_mb_syn_cabac.cpp */,
9AED66651946A2B3009A3567 /* utils.cpp */,
4CE446DD18BC605C0017DF25 /* au_set.cpp */,
4CE446DE18BC605C0017DF25 /* deblocking.cpp */,
@@ -446,6 +456,7 @@
F5BE8005196B913200ED02ED /* memory_aarch64_neon.S in Sources */,
4CBC1B83194ACBB400214D9E /* intra_pred_aarch64_neon.S in Sources */,
4CE4471718BC605C0017DF25 /* mc.cpp in Sources */,
F7E9994519EBD1E9009B1021 /* svc_set_mb_syn_cabac.cpp in Sources */,
F5617A50196A833A006E2B20 /* reconstruct_aarch64_neon.S in Sources */,
4CE4472918BC605C0017DF25 /* svc_set_mb_syn_cavlc.cpp in Sources */,
4CE4471818BC605C0017DF25 /* md.cpp in Sources */,
@@ -465,6 +476,7 @@
6CA38DA51991D31A003EAAE0 /* svc_motion_estimation_aarch64_neon.S in Sources */,
4CE4471418BC605C0017DF25 /* encoder_ext.cpp in Sources */,
4C34067218C57D0400DFA14A /* reconstruct_neon.S in Sources */,
F7E9994919EBD1F8009B1021 /* set_mb_syn_cabac.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -655,6 +655,10 @@
RelativePath="..\..\..\decoder\core\inc\bit_stream.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\cabac_decoder.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\copy_mb.h"
>
@@ -775,6 +779,10 @@
RelativePath="..\..\..\decoder\core\inc\parameter_sets.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cabac.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cavlc.h"
>
@@ -832,6 +840,10 @@
RelativePath="..\..\..\decoder\core\src\bit_stream.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\cabac_decoder.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\common_tables.cpp"
>
@@ -912,6 +924,10 @@
RelativePath="..\..\..\decoder\core\src\mv_pred.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cabac.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cavlc.cpp"
>

View File

@@ -429,6 +429,10 @@
RelativePath="..\..\..\encoder\core\src\sample.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\set_mb_syn_cabac.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\set_mb_syn_cavlc.cpp"
>
@@ -461,6 +465,10 @@
RelativePath="..\..\..\encoder\core\src\svc_motion_estimate.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\svc_set_mb_syn_cabac.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\svc_set_mb_syn_cavlc.cpp"
>
@@ -626,6 +634,10 @@
RelativePath="..\..\..\encoder\core\inc\sample.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\set_mb_syn_cabac.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\set_mb_syn_cavlc.h"
>
@@ -678,6 +690,10 @@
RelativePath="..\..\..\encoder\core\inc\svc_motion_estimate.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\svc_set_mb_syn.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\svc_set_mb_syn_cavlc.h"
>

View File

@@ -42,6 +42,7 @@
#include <math.h>
#include <assert.h>
#include <string.h>
#include "typedefs.h"
@@ -116,6 +117,10 @@
#define WELS_ROUND(x) ((int32_t)(0.5+(x)))
#endif//WELS_ROUND
#ifndef WELS_ROUND64
#define WELS_ROUND64(x) ((int64_t)(0.5+(x)))
#endif//WELS_ROUND
#ifndef WELS_DIV_ROUND
#define WELS_DIV_ROUND(x,y) ((int32_t)((y)==0?((x)/((y)+1)):(((y)/2+(x))/(y))))
#endif//WELS_DIV_ROUND
@@ -268,6 +273,37 @@ static inline bool WELS_POWER2_IF (uint32_t v) {
#define WELS_GCC_UNUSED
#endif
inline bool CheckInRangeCloseOpen (const int16_t kiCurrent, const int16_t kiMin, const int16_t kiMax) {
return ((kiCurrent >= kiMin) && (kiCurrent < kiMax));
}
static inline void WelsSetMemUint32_c (uint32_t* pDst, uint32_t iValue, int32_t iSizeOfData) {
for (int i = 0; i < iSizeOfData; i++) {
pDst[i] = iValue;
}
}
static inline void WelsSetMemUint16_c (uint16_t* pDst, uint16_t iValue, int32_t iSizeOfData) {
for (int i = 0; i < iSizeOfData; i++) {
pDst[i] = iValue;
}
}
inline void WelsSetMemMultiplebytes_c (void* pDst, uint32_t iValue, int32_t iSizeOfData, int32_t iDataLengthOfData) {
assert (4 == iDataLengthOfData || 2 == iDataLengthOfData || 1 == iDataLengthOfData);
// TODO: consider add assembly for these functions
if (0 != iValue) {
if (4 == iDataLengthOfData) {
WelsSetMemUint32_c (static_cast<uint32_t*> (pDst), static_cast<uint32_t> (iValue), iSizeOfData);
} else if (2 == iDataLengthOfData) {
WelsSetMemUint16_c (static_cast<uint16_t*> (pDst), static_cast<uint16_t> (iValue), iSizeOfData);
} else {
memset (static_cast<uint8_t*> (pDst), static_cast<uint8_t> (iValue), iSizeOfData);
}
} else {
memset (static_cast<uint8_t*> (pDst), 0, iSizeOfData * iDataLengthOfData);
}
}
#endif//WELS_MACRO_UTILIZATIONS_H__

View File

@@ -42,6 +42,8 @@
namespace WelsCommon {
/*common use table*/
#define CTX_NA 0
#define WELS_CONTEXT_COUNT 460
#define LEVEL_NUMBER 17
typedef struct TagLevelLimits {
uint8_t uiLevelIdc; // level idc
@@ -56,6 +58,7 @@ typedef struct TagLevelLimits {
int16_t iMaxMvsPer2Mb; // Max number of motion vectors per two consecutive MBs
} SLevelLimits;
#define CpbBrNalFactor 1200 //baseline,main,and extended profiles.
extern const SLevelLimits g_ksLevelLimits[LEVEL_NUMBER];
extern const uint8_t g_kuiMbCountScan4Idx[24];
extern const uint8_t g_kuiCache30ScanIdx[16];
@@ -64,6 +67,9 @@ extern const uint8_t g_kuiCache48CountScan4Idx[24];
extern const ALIGNED_DECLARE (uint16_t, g_kuiDequantCoeff[52][8], 16);
extern const uint8_t g_kuiChromaQpTable[52];
extern const uint8_t g_kuiCabacRangeLps[64][4];
extern const int8_t g_kiCabacGlobalContextIdx[WELS_CONTEXT_COUNT][4][2];
extern const uint8_t g_kuiStateTransTable[64][2];
/*
* NAL Unit Type (5 Bits)
*/

View File

@@ -173,5 +173,519 @@ const SLevelLimits g_ksLevelLimits[LEVEL_NUMBER] = {
{51, 983040, 36864, 184320, 240000, 240000, -2048, 2047, 2, 16}, /* level 5.1 */
{52, 2073600, 36864, 184320, 240000, 240000, -2048, 2047, 2, 16} /* level 5.2 */
};
//for cabac
/* this table is from Table9-12 to Table 9-24 */
const int8_t g_kiCabacGlobalContextIdx[WELS_CONTEXT_COUNT][4][2] = {
//0-10 Table 9-12
{{20, -15}, {20, -15}, {20, -15}, {20, -15}},
{{2, 54}, {2, 54}, {2, 54}, {2, 54}},
{{3, 74}, {3, 74}, {3, 74}, {3, 74}},
{{20, -15}, {20, -15}, {20, -15}, {20, -15}},
{{2, 54}, {2, 54}, {2, 54}, {2, 54}},
{{3, 74}, {3, 74}, {3, 74}, {3, 74}},
{{ -28, 127}, { -28, 127}, { -28, 127}, { -28, 127}},
{{ -23, 104}, { -23, 104}, { -23, 104}, { -23, 104}},
{{ -6, 53}, { -6, 53}, { -6, 53}, { -6, 53}},
{{ -1, 54}, { -1, 54}, { -1, 54}, { -1, 54}},
{{7, 51}, {7, 51}, {7, 51}, {7, 51}},
//11-23 Table 9-13
{{CTX_NA, CTX_NA}, {23, 33}, {22, 25}, {29, 16}},
{{CTX_NA, CTX_NA}, {23, 2}, {34, 0}, {25, 0}},
{{CTX_NA, CTX_NA}, {21, 0}, {16, 0}, {14, 0}},
{{CTX_NA, CTX_NA}, {1, 9}, { -2, 9}, { -10, 51}},
{{CTX_NA, CTX_NA}, {0, 49}, {4, 41}, { -3, 62}},
{{CTX_NA, CTX_NA}, { -37, 118}, { -29, 118}, { -27, 99}},
{{CTX_NA, CTX_NA}, {5, 57}, {2, 65}, {26, 16}},
{{CTX_NA, CTX_NA}, { -13, 78}, { -6, 71}, { -4, 85}},
{{CTX_NA, CTX_NA}, { -11, 65}, { -13, 79}, { -24, 102}},
{{CTX_NA, CTX_NA}, {1, 62}, {5, 52}, {5, 57}},
{{CTX_NA, CTX_NA}, {12, 49}, {9, 50}, {6, 57}},
{{CTX_NA, CTX_NA}, { -4, 73}, { -3, 70}, { -17, 73}},
{{CTX_NA, CTX_NA}, {17, 50}, {10, 54}, {14, 57}},
//24-39 Table9-14
{{CTX_NA, CTX_NA}, {18, 64}, {26, 34}, {20, 40}},
{{CTX_NA, CTX_NA}, {9, 43}, {19, 22}, {20, 10}},
{{CTX_NA, CTX_NA}, {29, 0}, {40, 0}, {29, 0}},
{{CTX_NA, CTX_NA}, {26, 67}, {57, 2}, {54, 0}},
{{CTX_NA, CTX_NA}, {16, 90}, {41, 36}, {37, 42}},
{{CTX_NA, CTX_NA}, {9, 104}, {26, 69}, {12, 97}},
{{CTX_NA, CTX_NA}, { -46, 127}, { -45, 127}, { -32, 127}},
{{CTX_NA, CTX_NA}, { -20, 104}, { -15, 101}, { -22, 117}},
{{CTX_NA, CTX_NA}, {1, 67}, { -4, 76}, { -2, 74}},
{{CTX_NA, CTX_NA}, { -13, 78}, { -6, 71}, { -4, 85}},
{{CTX_NA, CTX_NA}, { -11, 65}, { -13, 79}, { -24, 102}},
{{CTX_NA, CTX_NA}, {1, 62}, {5, 52}, {5, 57}},
{{CTX_NA, CTX_NA}, { -6, 86}, {6, 69}, { -6, 93}},
{{CTX_NA, CTX_NA}, { -17, 95}, { -13, 90}, { -14, 88}},
{{CTX_NA, CTX_NA}, { -6, 61}, {0, 52}, { -6, 44}},
{{CTX_NA, CTX_NA}, {9, 45}, {8, 43}, {4, 55}},
//40-53 Table 9-15
{{CTX_NA, CTX_NA}, { -3, 69}, { -2, 69}, { -11, 89}},
{{CTX_NA, CTX_NA}, { -6, 81}, { -5, 82}, { -15, 103}},
{{CTX_NA, CTX_NA}, { -11, 96}, { -10, 96}, { -21, 116}},
{{CTX_NA, CTX_NA}, {6, 55}, {2, 59}, {19, 57}},
{{CTX_NA, CTX_NA}, {7, 67}, {2, 75}, {20, 58}},
{{CTX_NA, CTX_NA}, { -5, 86}, { -3, 87}, {4, 84}},
{{CTX_NA, CTX_NA}, {2, 88}, { -3, 100}, {6, 96}},
{{CTX_NA, CTX_NA}, {0, 58}, {1, 56}, {1, 63}},
{{CTX_NA, CTX_NA}, { -3, 76}, { -3, 74}, { -5, 85}},
{{CTX_NA, CTX_NA}, { -10, 94}, { -6, 85}, { -13, 106}},
{{CTX_NA, CTX_NA}, {5, 54}, {0, 59}, {5, 63}},
{{CTX_NA, CTX_NA}, {4, 69}, { -3, 81}, {6, 75}},
{{CTX_NA, CTX_NA}, { -3, 81}, { -7, 86}, { -3, 90}},
{{CTX_NA, CTX_NA}, {0, 88}, { -5, 95}, { -1, 101}},
//54-59 Table 9-16
{{CTX_NA, CTX_NA}, { -7, 67}, { -1, 66}, {3, 55}},
{{CTX_NA, CTX_NA}, { -5, 74}, { -1, 77}, { -4, 79}},
{{CTX_NA, CTX_NA}, { -4, 74}, {1, 70}, { -2, 75}},
{{CTX_NA, CTX_NA}, { -5, 80}, { -2, 86}, { -12, 97}},
{{CTX_NA, CTX_NA}, { -7, 72}, { -5, 72}, { -7, 50}},
{{CTX_NA, CTX_NA}, {1, 58}, {0, 61}, {1, 60}},
//60-69 Table 9-17
{{0, 41}, {0, 41}, {0, 41}, {0, 41}},
{{0, 63}, {0, 63}, {0, 63}, {0, 63}},
{{0, 63}, {0, 63}, {0, 63}, {0, 63}},
{{0, 63}, {0, 63}, {0, 63}, {0, 63}},
{{ -9, 83}, { -9, 83}, { -9, 83}, { -9, 83}},
{{4, 86}, {4, 86}, {4, 86}, {4, 86}},
{{0, 97}, {0, 97}, {0, 97}, {0, 97}},
{{ -7, 72}, { -7, 72}, { -7, 72}, { -7, 72}},
{{13, 41}, {13, 41}, {13, 41}, {13, 41}},
{{3, 62}, {3, 62}, {3, 62}, {3, 62}},
//70-104 Table 9-18
{{0, 11}, {0, 45}, {13, 15}, {7, 34}},
{{1, 55}, { -4, 78}, {7, 51}, { -9, 88}},
{{0, 69}, { -3, 96}, {2, 80}, { -20, 127}},
{{ -17, 127}, { -27, 126}, { -39, 127}, { -36, 127}},
{{ -13, 102}, { -28, 98}, { -18, 91}, { -17, 91}},
{{0, 82}, { -25, 101}, { -17, 96}, { -14, 95}},
{{ -7, 74}, { -23, 67}, { -26, 81}, { -25, 84}},
{{ -21, 107}, { -28, 82}, { -35, 98}, { -25, 86}},
{{ -27, 127}, { -20, 94}, { -24, 102}, { -12, 89}},
{{ -31, 127}, { -16, 83}, { -23, 97}, { -17, 91}},
{{ -24, 127}, { -22, 110}, { -27, 119}, { -31, 127}},
{{ -18, 95}, { -21, 91}, { -24, 99}, { -14, 76}},
{{ -27, 127}, { -18, 102}, { -21, 110}, { -18, 103}},
{{ -21, 114}, { -13, 93}, { -18, 102}, { -13, 90}},
{{ -30, 127}, { -29, 127}, { -36, 127}, { -37, 127}},
{{ -17, 123}, { -7, 92}, {0, 80}, {11, 80}},
{{ -12, 115}, { -5, 89}, { -5, 89}, {5, 76}},
{{ -16, 122}, { -7, 96}, { -7, 94}, {2, 84}},
{{ -11, 115}, { -13, 108}, { -4, 92}, {5, 78}},
{{ -12, 63}, { -3, 46}, {0, 39}, { -6, 55}},
{{ -2, 68}, { -1, 65}, {0, 65}, {4, 61}},
{{ -15, 84}, { -1, 57}, { -15, 84}, { -14, 83}},
{{ -13, 104}, { -9, 93}, { -35, 127}, { -37, 127}},
{{ -3, 70}, { -3, 74}, { -2, 73}, { -5, 79}},
{{ -8, 93}, { -9, 92}, { -12, 104}, { -11, 104}},
{{ -10, 90}, { -8, 87}, { -9, 91}, { -11, 91}},
{{ -30, 127}, { -23, 126}, { -31, 127}, { -30, 127}},
{{ -1, 74}, {5, 54}, {3, 55}, {0, 65}},
{{ -6, 97}, {6, 60}, {7, 56}, { -2, 79}},
{{ -7, 91}, {6, 59}, {7, 55}, {0, 72}},
{{ -20, 127}, {6, 69}, {8, 61}, { -4, 92}},
{{ -4, 56}, { -1, 48}, { -3, 53}, { -6, 56}},
{{ -5, 82}, {0, 68}, {0, 68}, {3, 68}},
{{ -7, 76}, { -4, 69}, { -7, 74}, { -8, 71}},
{{ -22, 125}, { -8, 88}, { -9, 88}, { -13, 98}},
//105-165 Table 9-19
{{ -7, 93}, { -2, 85}, { -13, 103}, { -4, 86}},
{{ -11, 87}, { -6, 78}, { -13, 91}, { -12, 88}},
{{ -3, 77}, { -1, 75}, { -9, 89}, { -5, 82}},
{{ -5, 71}, { -7, 77}, { -14, 92}, { -3, 72}},
{{ -4, 63}, {2, 54}, { -8, 76}, { -4, 67}},
{{ -4, 68}, {5, 50}, { -12, 87}, { -8, 72}},
{{ -12, 84}, { -3, 68}, { -23, 110}, { -16, 89}},
{{ -7, 62}, {1, 50}, { -24, 105}, { -9, 69}},
{{ -7, 65}, {6, 42}, { -10, 78}, { -1, 59}},
{{8, 61}, { -4, 81}, { -20, 112}, {5, 66}},
{{5, 56}, {1, 63}, { -17, 99}, {4, 57}},
{{ -2, 66}, { -4, 70}, { -78, 127}, { -4, 71}},
{{1, 64}, {0, 67}, { -70, 127}, { -2, 71}},
{{0, 61}, {2, 57}, { -50, 127}, {2, 58}},
{{ -2, 78}, { -2, 76}, { -46, 127}, { -1, 74}},
{{1, 50}, {11, 35}, { -4, 66}, { -4, 44}},
{{7, 52}, {4, 64}, { -5, 78}, { -1, 69}},
{{10, 35}, {1, 61}, { -4, 71}, {0, 62}},
{{0, 44}, {11, 35}, { -8, 72}, { -7, 51}},
{{11, 38}, {18, 25}, {2, 59}, { -4, 47}},
{{1, 45}, {12, 24}, { -1, 55}, { -6, 42}},
{{0, 46}, {13, 29}, { -7, 70}, { -3, 41}},
{{5, 44}, {13, 36}, { -6, 75}, { -6, 53}},
{{31, 17}, { -10, 93}, { -8, 89}, {8, 76}},
{{1, 51}, { -7, 73}, { -34, 119}, { -9, 78}},
{{7, 50}, { -2, 73}, { -3, 75}, { -11, 83}},
{{28, 19}, {13, 46}, {32, 20}, {9, 52}},
{{16, 33}, {9, 49}, {30, 22}, {0, 67}},
{{14, 62}, { -7, 100}, { -44, 127}, { -5, 90}},
{{ -13, 108}, {9, 53}, {0, 54}, {1, 67}},
{{ -15, 100}, {2, 53}, { -5, 61}, { -15, 72}},
{{ -13, 101}, {5, 53}, {0, 58}, { -5, 75}},
{{ -13, 91}, { -2, 61}, { -1, 60}, { -8, 80}},
{{ -12, 94}, {0, 56}, { -3, 61}, { -21, 83}},
{{ -10, 88}, {0, 56}, { -8, 67}, { -21, 64}},
{{ -16, 84}, { -13, 63}, { -25, 84}, { -13, 31}},
{{ -10, 86}, { -5, 60}, { -14, 74}, { -25, 64}},
{{ -7, 83}, { -1, 62}, { -5, 65}, { -29, 94}},
{{ -13, 87}, {4, 57}, {5, 52}, {9, 75}},
{{ -19, 94}, { -6, 69}, {2, 57}, {17, 63}},
{{1, 70}, {4, 57}, {0, 61}, { -8, 74}},
{{0, 72}, {14, 39}, { -9, 69}, { -5, 35}},
{{ -5, 74}, {4, 51}, { -11, 70}, { -2, 27}},
{{18, 59}, {13, 68}, {18, 55}, {13, 91}},
{{ -8, 102}, {3, 64}, { -4, 71}, {3, 65}},
{{ -15, 100}, {1, 61}, {0, 58}, { -7, 69}},
{{0, 95}, {9, 63}, {7, 61}, {8, 77}},
{{ -4, 75}, {7, 50}, {9, 41}, { -10, 66}},
{{2, 72}, {16, 39}, {18, 25}, {3, 62}},
{{ -11, 75}, {5, 44}, {9, 32}, { -3, 68}},
{{ -3, 71}, {4, 52}, {5, 43}, { -20, 81}},
{{15, 46}, {11, 48}, {9, 47}, {0, 30}},
{{ -13, 69}, { -5, 60}, {0, 44}, {1, 7}},
{{0, 62}, { -1, 59}, {0, 51}, { -3, 23}},
{{0, 65}, {0, 59}, {2, 46}, { -21, 74}},
{{21, 37}, {22, 33}, {19, 38}, {16, 66}},
{{ -15, 72}, {5, 44}, { -4, 66}, { -23, 124}},
{{9, 57}, {14, 43}, {15, 38}, {17, 37}},
{{16, 54}, { -1, 78}, {12, 42}, {44, -18}},
{{0, 62}, {0, 60}, {9, 34}, {50, -34}},
{{12, 72}, {9, 69}, {0, 89}, { -22, 127}},
//166-226 Table 9-20
{{24, 0}, {11, 28}, {4, 45}, {4, 39}},
{{15, 9}, {2, 40}, {10, 28}, {0, 42}},
{{8, 25}, {3, 44}, {10, 31}, {7, 34}},
{{13, 18}, {0, 49}, {33, -11}, {11, 29}},
{{15, 9}, {0, 46}, {52, -43}, {8, 31}},
{{13, 19}, {2, 44}, {18, 15}, {6, 37}},
{{10, 37}, {2, 51}, {28, 0}, {7, 42}},
{{12, 18}, {0, 47}, {35, -22}, {3, 40}},
{{6, 29}, {4, 39}, {38, -25}, {8, 33}},
{{20, 33}, {2, 62}, {34, 0}, {13, 43}},
{{15, 30}, {6, 46}, {39, -18}, {13, 36}},
{{4, 45}, {0, 54}, {32, -12}, {4, 47}},
{{1, 58}, {3, 54}, {102, -94}, {3, 55}},
{{0, 62}, {2, 58}, {0, 0}, {2, 58}},
{{7, 61}, {4, 63}, {56, -15}, {6, 60}},
{{12, 38}, {6, 51}, {33, -4}, {8, 44}},
{{11, 45}, {6, 57}, {29, 10}, {11, 44}},
{{15, 39}, {7, 53}, {37, -5}, {14, 42}},
{{11, 42}, {6, 52}, {51, -29}, {7, 48}},
{{13, 44}, {6, 55}, {39, -9}, {4, 56}},
{{16, 45}, {11, 45}, {52, -34}, {4, 52}},
{{12, 41}, {14, 36}, {69, -58}, {13, 37}},
{{10, 49}, {8, 53}, {67, -63}, {9, 49}},
{{30, 34}, { -1, 82}, {44, -5}, {19, 58}},
{{18, 42}, {7, 55}, {32, 7}, {10, 48}},
{{10, 55}, { -3, 78}, {55, -29}, {12, 45}},
{{17, 51}, {15, 46}, {32, 1}, {0, 69}},
{{17, 46}, {22, 31}, {0, 0}, {20, 33}},
{{0, 89}, { -1, 84}, {27, 36}, {8, 63}},
{{26, -19}, {25, 7}, {33, -25}, {35, -18}},
{{22, -17}, {30, -7}, {34, -30}, {33, -25}},
{{26, -17}, {28, 3}, {36, -28}, {28, -3}},
{{30, -25}, {28, 4}, {38, -28}, {24, 10}},
{{28, -20}, {32, 0}, {38, -27}, {27, 0}},
{{33, -23}, {34, -1}, {34, -18}, {34, -14}},
{{37, -27}, {30, 6}, {35, -16}, {52, -44}},
{{33, -23}, {30, 6}, {34, -14}, {39, -24}},
{{40, -28}, {32, 9}, {32, -8}, {19, 17}},
{{38, -17}, {31, 19}, {37, -6}, {31, 25}},
{{33, -11}, {26, 27}, {35, 0}, {36, 29}},
{{40, -15}, {26, 30}, {30, 10}, {24, 33}},
{{41, -6}, {37, 20}, {28, 18}, {34, 15}},
{{38, 1}, {28, 34}, {26, 25}, {30, 20}},
{{41, 17}, {17, 70}, {29, 41}, {22, 73}},
{{30, -6}, {1, 67}, {0, 75}, {20, 34}},
{{27, 3}, {5, 59}, {2, 72}, {19, 31}},
{{26, 22}, {9, 67}, {8, 77}, {27, 44}},
{{37, -16}, {16, 30}, {14, 35}, {19, 16}},
{{35, -4}, {18, 32}, {18, 31}, {15, 36}},
{{38, -8}, {18, 35}, {17, 35}, {15, 36}},
{{38, -3}, {22, 29}, {21, 30}, {21, 28}},
{{37, 3}, {24, 31}, {17, 45}, {25, 21}},
{{38, 5}, {23, 38}, {20, 42}, {30, 20}},
{{42, 0}, {18, 43}, {18, 45}, {31, 12}},
{{35, 16}, {20, 41}, {27, 26}, {27, 16}},
{{39, 22}, {11, 63}, {16, 54}, {24, 42}},
{{14, 48}, {9, 59}, {7, 66}, {0, 93}},
{{27, 37}, {9, 64}, {16, 56}, {14, 56}},
{{21, 60}, { -1, 94}, {11, 73}, {15, 57}},
{{12, 68}, { -2, 89}, {10, 67}, {26, 38}},
{{2, 97}, { -9, 108}, { -10, 116}, { -24, 127}},
//227-275 Table 9-21
{{ -3, 71}, { -6, 76}, { -23, 112}, { -24, 115}},
{{ -6, 42}, { -2, 44}, { -15, 71}, { -22, 82}},
{{ -5, 50}, {0, 45}, { -7, 61}, { -9, 62}},
{{ -3, 54}, {0, 52}, {0, 53}, {0, 53}},
{{ -2, 62}, { -3, 64}, { -5, 66}, {0, 59}},
{{0, 58}, { -2, 59}, { -11, 77}, { -14, 85}},
{{1, 63}, { -4, 70}, { -9, 80}, { -13, 89}},
{{ -2, 72}, { -4, 75}, { -9, 84}, { -13, 94}},
{{ -1, 74}, { -8, 82}, { -10, 87}, { -11, 92}},
{{ -9, 91}, { -17, 102}, { -34, 127}, { -29, 127}},
{{ -5, 67}, { -9, 77}, { -21, 101}, { -21, 100}},
{{ -5, 27}, {3, 24}, { -3, 39}, { -14, 57}},
{{ -3, 39}, {0, 42}, { -5, 53}, { -12, 67}},
{{ -2, 44}, {0, 48}, { -7, 61}, { -11, 71}},
{{0, 46}, {0, 55}, { -11, 75}, { -10, 77}},
{{ -16, 64}, { -6, 59}, { -15, 77}, { -21, 85}},
{{ -8, 68}, { -7, 71}, { -17, 91}, { -16, 88}},
{{ -10, 78}, { -12, 83}, { -25, 107}, { -23, 104}},
{{ -6, 77}, { -11, 87}, { -25, 111}, { -15, 98}},
{{ -10, 86}, { -30, 119}, { -28, 122}, { -37, 127}},
{{ -12, 92}, {1, 58}, { -11, 76}, { -10, 82}},
{{ -15, 55}, { -3, 29}, { -10, 44}, { -8, 48}},
{{ -10, 60}, { -1, 36}, { -10, 52}, { -8, 61}},
{{ -6, 62}, {1, 38}, { -10, 57}, { -8, 66}},
{{ -4, 65}, {2, 43}, { -9, 58}, { -7, 70}},
{{ -12, 73}, { -6, 55}, { -16, 72}, { -14, 75}},
{{ -8, 76}, {0, 58}, { -7, 69}, { -10, 79}},
{{ -7, 80}, {0, 64}, { -4, 69}, { -9, 83}},
{{ -9, 88}, { -3, 74}, { -5, 74}, { -12, 92}},
{{ -17, 110}, { -10, 90}, { -9, 86}, { -18, 108}},
{{ -11, 97}, {0, 70}, {2, 66}, { -4, 79}},
{{ -20, 84}, { -4, 29}, { -9, 34}, { -22, 69}},
{{ -11, 79}, {5, 31}, {1, 32}, { -16, 75}},
{{ -6, 73}, {7, 42}, {11, 31}, { -2, 58}},
{{ -4, 74}, {1, 59}, {5, 52}, {1, 58}},
{{ -13, 86}, { -2, 58}, { -2, 55}, { -13, 78}},
{{ -13, 96}, { -3, 72}, { -2, 67}, { -9, 83}},
{{ -11, 97}, { -3, 81}, {0, 73}, { -4, 81}},
{{ -19, 117}, { -11, 97}, { -8, 89}, { -13, 99}},
{{ -8, 78}, {0, 58}, {3, 52}, { -13, 81}},
{{ -5, 33}, {8, 5}, {7, 4}, { -6, 38}},
{{ -4, 48}, {10, 14}, {10, 8}, { -13, 62}},
{{ -2, 53}, {14, 18}, {17, 8}, { -6, 58}},
{{ -3, 62}, {13, 27}, {16, 19}, { -2, 59}},
{{ -13, 71}, {2, 40}, {3, 37}, { -16, 73}},
{{ -10, 79}, {0, 58}, { -1, 61}, { -10, 76}},
{{ -12, 86}, { -3, 70}, { -5, 73}, { -13, 86}},
{{ -13, 90}, { -6, 79}, { -1, 70}, { -9, 83}},
{{ -14, 97}, { -8, 85}, { -4, 78}, { -10, 87}},
//276 no use
{{CTX_NA, CTX_NA}, {CTX_NA, CTX_NA}, {CTX_NA, CTX_NA}, {CTX_NA, CTX_NA}},
//277-337 Table 9-22
{{ -6, 93}, { -13, 106}, { -21, 126}, { -22, 127}},
{{ -6, 84}, { -16, 106}, { -23, 124}, { -25, 127}},
{{ -8, 79}, { -10, 87}, { -20, 110}, { -25, 120}},
{{0, 66}, { -21, 114}, { -26, 126}, { -27, 127}},
{{ -1, 71}, { -18, 110}, { -25, 124}, { -19, 114}},
{{0, 62}, { -14, 98}, { -17, 105}, { -23, 117}},
{{ -2, 60}, { -22, 110}, { -27, 121}, { -25, 118}},
{{ -2, 59}, { -21, 106}, { -27, 117}, { -26, 117}},
{{ -5, 75}, { -18, 103}, { -17, 102}, { -24, 113}},
{{ -3, 62}, { -21, 107}, { -26, 117}, { -28, 118}},
{{ -4, 58}, { -23, 108}, { -27, 116}, { -31, 120}},
{{ -9, 66}, { -26, 112}, { -33, 122}, { -37, 124}},
{{ -1, 79}, { -10, 96}, { -10, 95}, { -10, 94}},
{{0, 71}, { -12, 95}, { -14, 100}, { -15, 102}},
{{3, 68}, { -5, 91}, { -8, 95}, { -10, 99}},
{{10, 44}, { -9, 93}, { -17, 111}, { -13, 106}},
{{ -7, 62}, { -22, 94}, { -28, 114}, { -50, 127}},
{{15, 36}, { -5, 86}, { -6, 89}, { -5, 92}},
{{14, 40}, {9, 67}, { -2, 80}, {17, 57}},
{{16, 27}, { -4, 80}, { -4, 82}, { -5, 86}},
{{12, 29}, { -10, 85}, { -9, 85}, { -13, 94}},
{{1, 44}, { -1, 70}, { -8, 81}, { -12, 91}},
{{20, 36}, {7, 60}, { -1, 72}, { -2, 77}},
{{18, 32}, {9, 58}, {5, 64}, {0, 71}},
{{5, 42}, {5, 61}, {1, 67}, { -1, 73}},
{{1, 48}, {12, 50}, {9, 56}, {4, 64}},
{{10, 62}, {15, 50}, {0, 69}, { -7, 81}},
{{17, 46}, {18, 49}, {1, 69}, {5, 64}},
{{9, 64}, {17, 54}, {7, 69}, {15, 57}},
{{ -12, 104}, {10, 41}, { -7, 69}, {1, 67}},
{{ -11, 97}, {7, 46}, { -6, 67}, {0, 68}},
{{ -16, 96}, { -1, 51}, { -16, 77}, { -10, 67}},
{{ -7, 88}, {7, 49}, { -2, 64}, {1, 68}},
{{ -8, 85}, {8, 52}, {2, 61}, {0, 77}},
{{ -7, 85}, {9, 41}, { -6, 67}, {2, 64}},
{{ -9, 85}, {6, 47}, { -3, 64}, {0, 68}},
{{ -13, 88}, {2, 55}, {2, 57}, { -5, 78}},
{{4, 66}, {13, 41}, { -3, 65}, {7, 55}},
{{ -3, 77}, {10, 44}, { -3, 66}, {5, 59}},
{{ -3, 76}, {6, 50}, {0, 62}, {2, 65}},
{{ -6, 76}, {5, 53}, {9, 51}, {14, 54}},
{{10, 58}, {13, 49}, { -1, 66}, {15, 44}},
{{ -1, 76}, {4, 63}, { -2, 71}, {5, 60}},
{{ -1, 83}, {6, 64}, { -2, 75}, {2, 70}},
{{ -7, 99}, { -2, 69}, { -1, 70}, { -2, 76}},
{{ -14, 95}, { -2, 59}, { -9, 72}, { -18, 86}},
{{2, 95}, {6, 70}, {14, 60}, {12, 70}},
{{0, 76}, {10, 44}, {16, 37}, {5, 64}},
{{ -5, 74}, {9, 31}, {0, 47}, { -12, 70}},
{{0, 70}, {12, 43}, {18, 35}, {11, 55}},
{{ -11, 75}, {3, 53}, {11, 37}, {5, 56}},
{{1, 68}, {14, 34}, {12, 41}, {0, 69}},
{{0, 65}, {10, 38}, {10, 41}, {2, 65}},
{{ -14, 73}, { -3, 52}, {2, 48}, { -6, 74}},
{{3, 62}, {13, 40}, {12, 41}, {5, 54}},
{{4, 62}, {17, 32}, {13, 41}, {7, 54}},
{{ -1, 68}, {7, 44}, {0, 59}, { -6, 76}},
{{ -13, 75}, {7, 38}, {3, 50}, { -11, 82}},
{{11, 55}, {13, 50}, {19, 40}, { -2, 77}},
{{5, 64}, {10, 57}, {3, 66}, { -2, 77}},
{{12, 70}, {26, 43}, {18, 50}, {25, 42}},
//338-398 Table9-23
{{15, 6}, {14, 11}, {19, -6}, {17, -13}},
{{6, 19}, {11, 14}, {18, -6}, {16, -9}},
{{7, 16}, {9, 11}, {14, 0}, {17, -12}},
{{12, 14}, {18, 11}, {26, -12}, {27, -21}},
{{18, 13}, {21, 9}, {31, -16}, {37, -30}},
{{13, 11}, {23, -2}, {33, -25}, {41, -40}},
{{13, 15}, {32, -15}, {33, -22}, {42, -41}},
{{15, 16}, {32, -15}, {37, -28}, {48, -47}},
{{12, 23}, {34, -21}, {39, -30}, {39, -32}},
{{13, 23}, {39, -23}, {42, -30}, {46, -40}},
{{15, 20}, {42, -33}, {47, -42}, {52, -51}},
{{14, 26}, {41, -31}, {45, -36}, {46, -41}},
{{14, 44}, {46, -28}, {49, -34}, {52, -39}},
{{17, 40}, {38, -12}, {41, -17}, {43, -19}},
{{17, 47}, {21, 29}, {32, 9}, {32, 11}},
{{24, 17}, {45, -24}, {69, -71}, {61, -55}},
{{21, 21}, {53, -45}, {63, -63}, {56, -46}},
{{25, 22}, {48, -26}, {66, -64}, {62, -50}},
{{31, 27}, {65, -43}, {77, -74}, {81, -67}},
{{22, 29}, {43, -19}, {54, -39}, {45, -20}},
{{19, 35}, {39, -10}, {52, -35}, {35, -2}},
{{14, 50}, {30, 9}, {41, -10}, {28, 15}},
{{10, 57}, {18, 26}, {36, 0}, {34, 1}},
{{7, 63}, {20, 27}, {40, -1}, {39, 1}},
{{ -2, 77}, {0, 57}, {30, 14}, {30, 17}},
{{ -4, 82}, { -14, 82}, {28, 26}, {20, 38}},
{{ -3, 94}, { -5, 75}, {23, 37}, {18, 45}},
{{9, 69}, { -19, 97}, {12, 55}, {15, 54}},
{{ -12, 109}, { -35, 125}, {11, 65}, {0, 79}},
{{36, -35}, {27, 0}, {37, -33}, {36, -16}},
{{36, -34}, {28, 0}, {39, -36}, {37, -14}},
{{32, -26}, {31, -4}, {40, -37}, {37, -17}},
{{37, -30}, {27, 6}, {38, -30}, {32, 1}},
{{44, -32}, {34, 8}, {46, -33}, {34, 15}},
{{34, -18}, {30, 10}, {42, -30}, {29, 15}},
{{34, -15}, {24, 22}, {40, -24}, {24, 25}},
{{40, -15}, {33, 19}, {49, -29}, {34, 22}},
{{33, -7}, {22, 32}, {38, -12}, {31, 16}},
{{35, -5}, {26, 31}, {40, -10}, {35, 18}},
{{33, 0}, {21, 41}, {38, -3}, {31, 28}},
{{38, 2}, {26, 44}, {46, -5}, {33, 41}},
{{33, 13}, {23, 47}, {31, 20}, {36, 28}},
{{23, 35}, {16, 65}, {29, 30}, {27, 47}},
{{13, 58}, {14, 71}, {25, 44}, {21, 62}},
{{29, -3}, {8, 60}, {12, 48}, {18, 31}},
{{26, 0}, {6, 63}, {11, 49}, {19, 26}},
{{22, 30}, {17, 65}, {26, 45}, {36, 24}},
{{31, -7}, {21, 24}, {22, 22}, {24, 23}},
{{35, -15}, {23, 20}, {23, 22}, {27, 16}},
{{34, -3}, {26, 23}, {27, 21}, {24, 30}},
{{34, 3}, {27, 32}, {33, 20}, {31, 29}},
{{36, -1}, {28, 23}, {26, 28}, {22, 41}},
{{34, 5}, {28, 24}, {30, 24}, {22, 42}},
{{32, 11}, {23, 40}, {27, 34}, {16, 60}},
{{35, 5}, {24, 32}, {18, 42}, {15, 52}},
{{34, 12}, {28, 29}, {25, 39}, {14, 60}},
{{39, 11}, {23, 42}, {18, 50}, {3, 78}},
{{30, 29}, {19, 57}, {12, 70}, { -16, 123}},
{{34, 26}, {22, 53}, {21, 54}, {21, 53}},
{{29, 39}, {22, 61}, {14, 71}, {22, 56}},
{{19, 66}, {11, 86}, {11, 83}, {25, 61}},
{{31, 21}, {12, 40}, {25, 32}, {21, 33}},
{{31, 31}, {11, 51}, {21, 49}, {19, 50}},
{{25, 50}, {14, 59}, {21, 54}, {17, 61}},
//402-459 Table 9-24
{{ -17, 120}, { -4, 79}, { -5, 85}, { -3, 78}},
{{ -20, 112}, { -7, 71}, { -6, 81}, { -8, 74}},
{{ -18, 114}, { -5, 69}, { -10, 77}, { -9, 72}},
{{ -11, 85}, { -9, 70}, { -7, 81}, { -10, 72}},
{{ -15, 92}, { -8, 66}, { -17, 80}, { -18, 75}},
{{ -14, 89}, { -10, 68}, { -18, 73}, { -12, 71}},
{{ -26, 71}, { -19, 73}, { -4, 74}, { -11, 63}},
{{ -15, 81}, { -12, 69}, { -10, 83}, { -5, 70}},
{{ -14, 80}, { -16, 70}, { -9, 71}, { -17, 75}},
{{0, 68}, { -15, 67}, { -9, 67}, { -14, 72}},
{{ -14, 70}, { -20, 62}, { -1, 61}, { -16, 67}},
{{ -24, 56}, { -19, 70}, { -8, 66}, { -8, 53}},
{{ -23, 68}, { -16, 66}, { -14, 66}, { -14, 59}},
{{ -24, 50}, { -22, 65}, {0, 59}, { -9, 52}},
{{ -11, 74}, { -20, 63}, {2, 59}, { -11, 68}},
{{23, -13}, {9, -2}, {17, -10}, {9, -2}},
{{26, -13}, {26, -9}, {32, -13}, {30, -10}},
{{40, -15}, {33, -9}, {42, -9}, {31, -4}},
{{49, -14}, {39, -7}, {49, -5}, {33, -1}},
{{44, 3}, {41, -2}, {53, 0}, {33, 7}},
{{45, 6}, {45, 3}, {64, 3}, {31, 12}},
{{44, 34}, {49, 9}, {68, 10}, {37, 23}},
{{33, 54}, {45, 27}, {66, 27}, {31, 38}},
{{19, 82}, {36, 59}, {47, 57}, {20, 64}},
{{ -3, 75}, { -6, 66}, { -5, 71}, { -9, 71}},
{{ -1, 23}, { -7, 35}, {0, 24}, { -7, 37}},
{{1, 34}, { -7, 42}, { -1, 36}, { -8, 44}},
{{1, 43}, { -8, 45}, { -2, 42}, { -11, 49}},
{{0, 54}, { -5, 48}, { -2, 52}, { -10, 56}},
{{ -2, 55}, { -12, 56}, { -9, 57}, { -12, 59}},
{{0, 61}, { -6, 60}, { -6, 63}, { -8, 63}},
{{1, 64}, { -5, 62}, { -4, 65}, { -9, 67}},
{{0, 68}, { -8, 66}, { -4, 67}, { -6, 68}},
{{ -9, 92}, { -8, 76}, { -7, 82}, { -10, 79}},
{{ -14, 106}, { -5, 85}, { -3, 81}, { -3, 78}},
{{ -13, 97}, { -6, 81}, { -3, 76}, { -8, 74}},
{{ -15, 90}, { -10, 77}, { -7, 72}, { -9, 72}},
{{ -12, 90}, { -7, 81}, { -6, 78}, { -10, 72}},
{{ -18, 88}, { -17, 80}, { -12, 72}, { -18, 75}},
{{ -10, 73}, { -18, 73}, { -14, 68}, { -12, 71}},
{{ -9, 79}, { -4, 74}, { -3, 70}, { -11, 63}},
{{ -14, 86}, { -10, 83}, { -6, 76}, { -5, 70}},
{{ -10, 73}, { -9, 71}, { -5, 66}, { -17, 75}},
{{ -10, 70}, { -9, 67}, { -5, 62}, { -14, 72}},
{{ -10, 69}, { -1, 61}, {0, 57}, { -16, 67}},
{{ -5, 66}, { -8, 66}, { -4, 61}, { -8, 53}},
{{ -9, 64}, { -14, 66}, { -9, 60}, { -14, 59}},
{{ -5, 58}, {0, 59}, {1, 54}, { -9, 52}},
{{2, 59}, {2, 59}, {2, 58}, { -11, 68}},
{{21, -10}, {21, -13}, {17, -10}, {9, -2}},
{{24, -11}, {33, -14}, {32, -13}, {30, -10}},
{{28, -8}, {39, -7}, {42, -9}, {31, -4}},
{{28, -1}, {46, -2}, {49, -5}, {33, -1}},
{{29, 3}, {51, 2}, {53, 0}, {33, 7}},
{{29, 9}, {60, 6}, {64, 3}, {31, 12}},
{{35, 20}, {61, 17}, {68, 10}, {37, 23}},
{{29, 36}, {55, 34}, {66, 27}, {31, 38}},
{{14, 67}, {42, 62}, {47, 57}, {20, 64}},
};
/*Table 9-44 Specification of rangeTabLPS depending on pStateIdx and qCodIRangeIdx */
const uint8_t g_kuiCabacRangeLps[64][4] = {
{ 128, 176, 208, 240}, { 128, 167, 197, 227}, { 128, 158, 187, 216}, { 123, 150, 178, 205}, { 116, 142, 169, 195}, { 111, 135, 160, 185}, { 105, 128, 152, 175}, { 100, 122, 144, 166},
{ 95, 116, 137, 158}, { 90, 110, 130, 150}, { 85, 104, 123, 142}, { 81, 99, 117, 135}, { 77, 94, 111, 128}, { 73, 89, 105, 122}, { 69, 85, 100, 116}, { 66, 80, 95, 110},
{ 62, 76, 90, 104}, { 59, 72, 86, 99}, { 56, 69, 81, 94}, { 53, 65, 77, 89}, { 51, 62, 73, 85}, { 48, 59, 69, 80}, { 46, 56, 66, 76}, { 43, 53, 63, 72},
{ 41, 50, 59, 69}, { 39, 48, 56, 65}, { 37, 45, 54, 62}, { 35, 43, 51, 59}, { 33, 41, 48, 56}, { 32, 39, 46, 53}, { 30, 37, 43, 50}, { 29, 35, 41, 48},
{ 27, 33, 39, 45}, { 26, 31, 37, 43}, { 24, 30, 35, 41}, { 23, 28, 33, 39}, { 22, 27, 32, 37}, { 21, 26, 30, 35}, { 20, 24, 29, 33}, { 19, 23, 27, 31},
{ 18, 22, 26, 30}, { 17, 21, 25, 28}, { 16, 20, 23, 27}, { 15, 19, 22, 25}, { 14, 18, 21, 24}, { 14, 17, 20, 23}, { 13, 16, 19, 22}, { 12, 15, 18, 21},
{ 12, 14, 17, 20}, { 11, 14, 16, 19}, { 11, 13, 15, 18}, { 10, 12, 15, 17}, { 10, 12, 14, 16}, { 9, 11, 13, 15}, { 9, 11, 12, 14}, { 8, 10, 12, 14},
{ 8, 9, 11, 13}, { 7, 9, 11, 12}, { 7, 9, 10, 12}, { 7, 8, 10, 11}, { 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2}
};
/*Table 9-45 State transition table*/
const uint8_t g_kuiStateTransTable[64][2] = {
{0, 1}, {0, 2}, {1, 3}, {2, 4}, {2, 5}, {4, 6}, {4, 7}, {5, 8}, {6, 9}, {7, 10},
{8, 11}, {9, 12}, {9, 13}, {11, 14}, {11, 15}, {12, 16}, {13, 17}, {13, 18}, {15, 19}, {15, 20},
{16, 21}, {16, 22}, {18, 23}, {18, 24}, {19, 25}, {19, 26}, {21, 27}, {21, 28}, {22, 29}, {22, 30},
{23, 31}, {24, 32}, {24, 33}, {25, 34}, {26, 35}, {26, 36}, {27, 37}, {27, 38}, {28, 39}, {29, 40},
{29, 41}, {30, 42}, {30, 43}, {30, 44}, {31, 45}, {32, 46}, {32, 47}, {33, 48}, {33, 49}, {33, 50},
{34, 51}, {34, 52}, {35, 53}, {35, 54}, {35, 55}, {36, 56}, {36, 57}, {36, 58}, {37, 59}, {37, 60},
{37, 61}, {38, 62}, {38, 62}, {63, 63}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

View File

@@ -336,6 +336,7 @@ HRESULT CD3D9ExUtils::Render (void* pDst[3], SBufferInfo* pInfo) {
|| m_nHeight != pInfo->UsrData.sSystemBuffer.iHeight) {
m_nWidth = pInfo->UsrData.sSystemBuffer.iWidth;
m_nHeight = pInfo->UsrData.sSystemBuffer.iHeight;
MoveWindow(m_hWnd,0,0,pInfo->UsrData.sSystemBuffer.iWidth,pInfo->UsrData.sSystemBuffer.iHeight,true);
SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
SAFE_RELEASE (m_lpD3D9Device);
}

View File

@@ -63,12 +63,18 @@ using namespace std;
//using namespace WelsDec;
//#define STICK_STREAM_SIZE // For Demo interfaces test with track file of integrated frames
//#define NO_DELAY_DECODING // For Demo interfaces test with no delay decoding
void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, const char* kpOuputFileName,
int32_t& iWidth, int32_t& iHeight, const char* pOptionFileName) {
FILE* pH264File = NULL;
FILE* pYuvFile = NULL;
FILE* pOptionFile = NULL;
#if defined ( STICK_STREAM_SIZE )
FILE* fpTrack = fopen ("3.len", "rb");
unsigned long pInfo[4];
#endif// STICK_STREAM_SIZE
unsigned long long uiTimeStamp = 0;
int64_t iStart = 0, iEnd = 0, iTotal = 0;
int32_t iSliceSize;
int32_t iSliceIndex = 0;
@@ -153,12 +159,6 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
goto label_exit;
}
#if defined ( STICK_STREAM_SIZE )
FILE* fpTrack = fopen ("3.len", "rb");
#endif// STICK_STREAM_SIZE
while (true) {
if (iBufPos >= iFileSize) {
@@ -169,8 +169,10 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
}
#if defined ( STICK_STREAM_SIZE )
if (fpTrack)
fread (&iSliceSize, 1, sizeof (int32_t), fpTrack);
if (fpTrack) {
fread (pInfo, 4, sizeof (unsigned long), fpTrack);
iSliceSize = static_cast<int32_t>(pInfo[2]);
}
#else
for (i = 0; i < iFileSize; i++) {
if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
@@ -198,7 +200,7 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
pDecoder->GetOption (DECODER_OPTION_VCL_NAL, &iFeedbackVclNalInAu);
int32_t iFeedbackTidInAu;
pDecoder->GetOption (DECODER_OPTION_TEMPORAL_ID, &iFeedbackTidInAu);
int32_t iErrorConMethod = (int32_t) ERROR_CON_SLICE_COPY;
int32_t iErrorConMethod = (int32_t) ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
//~end for
@@ -206,8 +208,9 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
pData[0] = NULL;
pData[1] = NULL;
pData[2] = NULL;
uiTimeStamp ++;
memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
if (sDstBufInfo.iBufferStatus == 1) {
@@ -234,6 +237,38 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
++ iFrameCount;
}
#ifdef NO_DELAY_DECODING
iStart = WelsTime();
pData[0] = NULL;
pData[1] = NULL;
pData[2] = NULL;
memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
if (sDstBufInfo.iBufferStatus == 1) {
pDst[0] = pData[0];
pDst[1] = pData[1];
pDst[2] = pData[2];
}
iEnd = WelsTime();
iTotal += iEnd - iStart;
if (sDstBufInfo.iBufferStatus == 1) {
cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
if (pOptionFile != NULL) {
if (iWidth != iLastWidth && iHeight != iLastHeight) {
fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
fwrite (&iWidth , sizeof (iWidth) , 1, pOptionFile);
fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
iLastWidth = iWidth;
iLastHeight = iHeight;
}
}
++ iFrameCount;
}
#endif
iBufPos += iSliceSize;
++ iSliceIndex;
}

View File

@@ -238,6 +238,8 @@ int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSv
pSvcParam.bEnableSSEI = atoi (strTag[1].c_str()) ? true : false;
} else if (strTag[0].compare ("EnableFrameCropping") == 0) {
pSvcParam.bEnableFrameCroppingFlag = (atoi (strTag[1].c_str()) != 0);
} else if (strTag[0].compare ("EntropyCodingModeFlag") == 0) {
pSvcParam.iEntropyCodingModeFlag = (atoi (strTag[1].c_str()) != 0);
} else if (strTag[0].compare ("LoopFilterDisableIDC") == 0) {
pSvcParam.iLoopFilterDisableIdc = (int8_t)atoi (strTag[1].c_str());
if (pSvcParam.iLoopFilterDisableIdc > 6 || pSvcParam.iLoopFilterDisableIdc < 0) {
@@ -354,6 +356,7 @@ void PrintHelp() {
printf (" -iper Intra period (default: -1) : must be a power of 2 of GOP size (or -1)\n");
printf (" -nalsize the Maximum NAL size. which should be larger than the each layer slicesize when slice mode equals to SM_DYN_SLICE\n");
printf (" -spsid Enable id adding in SPS/PPS per IDR \n");
printf (" -cabac Entropy coding mode(0:cavlc 1:cabac \n");
printf (" -denois Control denoising (default: 0)\n");
printf (" -scene Control scene change detection (default: 0)\n");
printf (" -bgd Control background detection (default: 0)\n");
@@ -420,6 +423,9 @@ int ParseCommandLine (int argc, char** argv, SSourcePicture* pSrcPic, SEncParamE
else if (!strcmp (pCommand, "-spsid") && (n < argc))
pSvcParam.bEnableSpsPpsIdAddition = atoi (argv[n++]) ? true : false;
else if (!strcmp (pCommand, "-cabac") && (n < argc))
pSvcParam.iEntropyCodingModeFlag = atoi (argv[n++]);
else if (!strcmp (pCommand, "-denois") && (n < argc))
pSvcParam.bEnableDenoise = atoi (argv[n++]) ? true : false;
@@ -574,7 +580,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.iPicWidth = 1280; // width of picture in samples
sParam.iPicHeight = 720; // height of picture in samples
sParam.iTargetBitrate = 2500000; // target bitrate desired
sParam.iMaxBitrate = MAX_BIT_RATE;
sParam.iMaxBitrate = UNSPECIFIED_BIT_RATE;
sParam.iRCMode = RC_QUALITY_MODE; // rc mode control
sParam.iTemporalLayerNum = 3; // layer number at temporal level
sParam.iSpatialLayerNum = 4; // layer number at spatial level
@@ -594,7 +600,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 90;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 7.5f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 64000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
++ iIndexLayer;
@@ -603,7 +609,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 180;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 15.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 160000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
++ iIndexLayer;
@@ -612,7 +618,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 360;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 30.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 512000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;
@@ -622,7 +628,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 720;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 30.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 1500000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;

View File

@@ -156,4 +156,22 @@ WELS_ASM_FUNC_BEGIN IdctResAddPred_neon
vst1.32 {d22[0]},[r2],r1
vst1.32 {d22[1]},[r2]
WELS_ASM_FUNC_END
WELS_ASM_FUNC_BEGIN WelsBlockZero16x16_neon
veor q0, q0
veor q1, q1
lsl r1, r1, 1
.rept 16
vst1.64 {q0, q1}, [r0], r1
.endr
WELS_ASM_FUNC_END
WELS_ASM_FUNC_BEGIN WelsBlockZero8x8_neon
veor q0, q0
lsl r1, r1, 1
.rept 8
vst1.64 {q0}, [r0], r1
.endr
WELS_ASM_FUNC_END
#endif

View File

@@ -158,4 +158,21 @@ WELS_ASM_AARCH64_FUNC_BEGIN IdctResAddPred_AArch64_neon
st1 {v1.s}[0],[x2],x1
st1 {v1.s}[1],[x2]
WELS_ASM_AARCH64_FUNC_END
WELS_ASM_AARCH64_FUNC_BEGIN WelsBlockZero16x16_AArch64_neon
eor v0.16b, v0.16b, v0.16b
eor v1.16b, v1.16b, v1.16b
lsl x1, x1, 1
.rept 16
st1 {v0.16b, v1.16b}, [x0], x1
.endr
WELS_ASM_AARCH64_FUNC_END
WELS_ASM_AARCH64_FUNC_BEGIN WelsBlockZero8x8_AArch64_neon
eor v0.16b, v0.16b, v0.16b
lsl x1, x1, 1
.rept 8
st1 {v0.16b}, [x0], x1
.endr
WELS_ASM_AARCH64_FUNC_END
#endif

View File

@@ -86,7 +86,7 @@ uint8_t* DetectStartCodePrefix (const uint8_t* kpBuf, int32_t* pOffset, int32_t
uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeader, uint8_t* pSrcRbsp,
int32_t iSrcRbspLen, uint8_t* pSrcNal, int32_t iSrcNalLen, int32_t* pConsumedBytes);
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen);
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen, uint8_t* pSrcNal, const int32_t kSrcNalLen);
int32_t ParseRefBasePicMarking (PBitStringAux pBs, PRefBasePicMarking pRefBasePicMarking);
@@ -113,7 +113,7 @@ bool CheckNextAuNewSeq (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const
* \note Call it in case eNalUnitType is SPS.
*************************************************************************************
*/
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight);
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight, uint8_t* pSrcNal, const int32_t kSrcNalLen);
/*!
*************************************************************************************
@@ -129,7 +129,7 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
* \note Call it in case eNalUnitType is PPS.
*************************************************************************************
*/
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux);
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal, const int32_t kSrcNalLen);
/*!
*************************************************************************************

View File

@@ -35,7 +35,6 @@
#define WELS_BIT_STREAM_H__
#include "typedefs.h"
namespace WelsDec {
/*
@@ -64,9 +63,17 @@ typedef struct TagBitStringAux {
*/
int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize);
void InitReadBits (PBitStringAux pBitString);
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset);
//The following for writing bs in decoder for Parse Only purpose
void DecInitBitsForEncoding (PBitStringAux pBitString, uint8_t* kpBuf, const int32_t kiSize);
int32_t DecBsWriteBits (PBitStringAux pBitString, int32_t iLen, const uint32_t kuiValue);
int32_t DecBsWriteOneBit (PBitStringAux pBitString, const uint32_t kuiValue);
int32_t DecBsFlush (PBitStringAux pBitString);
int32_t DecBsWriteUe (PBitStringAux pBitString, const uint32_t kuiValue);
int32_t DecBsWriteSe (PBitStringAux pBitString, const int32_t kiValue);
int32_t DecBsRbspTrailingBits (PBitStringAux pBitString);
void RBSP2EBSP (uint8_t* pDstBuf, uint8_t* pSrcBuf, const int32_t kiSize);
} // namespace WelsDec

View File

@@ -0,0 +1,111 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \file cabac_decoder.h
*
* \brief Interfaces introduced for cabac decoder
*
* \date 10/10/2014 Created
*
*************************************************************************************
*/
#ifndef WELS_CABAC_DECODER_H__
#define WELS_CABAC_DECODER_H__
#include "decoder_context.h"
#include "error_code.h"
#include "wels_common_defs.h"
namespace WelsDec {
static const uint8_t g_kRenormTable256[256] = {
6, 6, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 5, 5, 5, 5,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
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, 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,
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. CABAC context initialization
void WelsCabacGlobalInit(PWelsDecoderContext pCabacCtx);
void WelsCabacContextInit (PWelsDecoderContext pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp);
//2. decoding Engine initialization
int32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
//3. actual decoding
int32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead);
int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBit);
int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
int32_t DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
//4. unary parsing
int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,
uint32_t& uiSymVal);
//5. EXGk parsing
int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal);
uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal);
int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxC, uint32_t& uiCode);
#define WELS_CABAC_HALF 0x01FE
#define WELS_CABAC_QUARTER 0x0100
#define WELS_CABAC_FALSE_RETURN(iErrorInfo) \
if(iErrorInfo) { \
return iErrorInfo; \
}
}
#endif

View File

@@ -66,10 +66,12 @@ struct TagDqLayer {
int8_t* pMbType;
int32_t* pSliceIdc; // using int32_t for slice_idc
int16_t (*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
int16_t (*pMvd[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
int8_t (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
int8_t* pLumaQp;
int8_t* pChromaQp;
int8_t* pCbp;
uint8_t *pCbfDc;
int8_t (*pNzc)[24];
int8_t (*pNzcRs)[24];
int8_t* pResidualPredFlag;

View File

@@ -219,7 +219,7 @@ static inline int32_t BsGetTe0 (PBitStringAux pBs, int32_t iRange, uint32_t* pCo
static inline int32_t BsGetTrailingBits (uint8_t* pBuf) {
// TODO
uint32_t uiValue = *pBuf;
int32_t iRetNum = 1;
int32_t iRetNum = 0;
do {
if (uiValue & 1)

View File

@@ -38,17 +38,21 @@
namespace WelsDec {
int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx);
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx);
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
typedef int32_t (*PWelsDecMbCavlcFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur);
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
typedef int32_t (*PWelsDecMbFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacISlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacPSlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacISliceBaseMode0(PWelsDecoderContext pCtx, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacPSliceBaseMode0(PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag);
int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx); //construction based on slice
int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur);
int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx);
int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput);
@@ -63,12 +67,21 @@ void WelsChromaDcIdct (int16_t* pBlock);
extern "C" {
#endif//__cplusplus
#if defined(X86_ASM)
void WelsBlockZero16x16_sse2(int16_t * block, int32_t stride);
void WelsBlockZero8x8_sse2(int16_t * block, int32_t stride);
#endif
#if defined(HAVE_NEON)
void SetNonZeroCount_neon (int8_t* pNonZeroCount);
void WelsBlockZero16x16_neon(int16_t * block, int32_t stride);
void WelsBlockZero8x8_neon(int16_t * block, int32_t stride);
#endif
#if defined(HAVE_NEON_AARCH64)
void SetNonZeroCount_AArch64_neon (int8_t* pNonZeroCount);
void WelsBlockZero16x16_AArch64_neon(int16_t * block, int32_t stride);
void WelsBlockZero8x8_AArch64_neon(int16_t * block, int32_t stride);
#endif
#ifdef __cplusplus
}
@@ -77,6 +90,8 @@ void SetNonZeroCount_AArch64_neon (int8_t* pNonZeroCount);
void SetNonZeroCount_c (int8_t* pNonZeroCount);
void WelsBlockFuncInit (SBlockFunc* pFunc, int32_t iCpu);
void WelsBlockZero16x16_c(int16_t * block, int32_t stride);
void WelsBlockZero8x8_c(int16_t * block, int32_t stride);
} // namespace WelsDec

View File

@@ -68,7 +68,7 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
* \note N/A
*************************************************************************************
*/
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx);
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx);
/*!
*************************************************************************************
@@ -101,7 +101,7 @@ void WelsEndDecoder (PWelsDecoderContext pCtx);
*/
int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
uint8_t** ppDst, SBufferInfo* pDstBufInfo);
uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo);
/*
* request memory blocks for decoder avc part
@@ -132,8 +132,6 @@ int32_t SyncPictureResolutionExt (PWelsDecoderContext pCtx, const int32_t kiMbWi
void AssignFuncPointerForRec (PWelsDecoderContext pCtx);
void ResetParameterSetsState (PWelsDecoderContext pCtx);
void GetVclNalTemporalId (PWelsDecoderContext pCtx); //get the info that whether or not have VCL NAL in current AU,
//and if YES, get the temporal ID

View File

@@ -43,6 +43,7 @@
#include "utils.h"
#include "wels_const.h"
#include "wels_common_basis.h"
#include "wels_common_defs.h"
#include "codec_app_def.h"
#include "parameter_sets.h"
#include "nalu.h"
@@ -56,6 +57,42 @@
#include "expand_pic.h"
namespace WelsDec {
#define MAX_PRED_MODE_ID_I16x16 3
#define MAX_PRED_MODE_ID_CHROMA 3
#define MAX_PRED_MODE_ID_I4x4 8
#define WELS_QP_MAX 51
typedef struct SWels_Cabac_Element {
uint8_t uiState;
uint8_t uiMPS;
}SWelsCabacCtx, *PWelsCabacCtx;
typedef struct
{
uint64_t uiRange;
uint64_t uiOffset;
int32_t iBitsLeft;
uint8_t *pBuffStart;
uint8_t *pBuffCurr;
uint8_t *pBuffEnd;
} SWelsCabacDecEngine, *PWelsCabacDecEngine;
#define NEW_CTX_OFFSET_MB_TYPE_I 3
#define NEW_CTX_OFFSET_SKIP 11
#define NEW_CTX_OFFSET_SUBMB_TYPE 21
#define NEW_CTX_OFFSET_MVD 40
#define NEW_CTX_OFFSET_REF_NO 54
#define NEW_CTX_OFFSET_DELTA_QP 60
#define NEW_CTX_OFFSET_IPR 68
#define NEW_CTX_OFFSET_CIPR 64
#define NEW_CTX_OFFSET_CBP 73
#define NEW_CTX_OFFSET_CBF 85
#define NEW_CTX_OFFSET_MAP 105
#define NEW_CTX_OFFSET_LAST 166
#define NEW_CTX_OFFSET_ONE 227
#define NEW_CTX_OFFSET_ABS 232
#define CTX_NUM_MVD 7
#define CTX_NUM_CBP 4
typedef struct TagDataBuffer {
uint8_t* pHead;
@@ -65,6 +102,19 @@ uint8_t* pStartPos;
uint8_t* pCurPos;
} SDataBuffer;
//limit size for SPS PPS total permitted size for parse_only
#define SPS_PPS_BS_SIZE 128
typedef struct TagSpsBsInfo {
uint8_t pSpsBsBuf [SPS_PPS_BS_SIZE];
int32_t iSpsId;
uint16_t uiSpsBsLen;
} SSpsBsInfo;
typedef struct TagPpsBsInfo {
uint8_t pPpsBsBuf [SPS_PPS_BS_SIZE];
int32_t iPpsId;
uint16_t uiPpsBsLen;
} SPpsBsInfo;
//#ifdef __cplusplus
//extern "C" {
//#endif//__cplusplus
@@ -141,16 +191,20 @@ PChromaDeblockingEQ4Func pfChromaDeblockingEQ4Hor;
} SDeblockingFunc, *PDeblockingFunc;
typedef void (*PWelsNonZeroCountFunc) (int8_t* pNonZeroCount);
typedef void (*PWelsBlockZeroFunc) (int16_t* block,int32_t stride);
typedef struct TagBlockFunc {
PWelsNonZeroCountFunc pWelsSetNonZeroCountFunc;
PWelsBlockZeroFunc pWelsBlockZero16x16Func;
PWelsBlockZeroFunc pWelsBlockZero8x8Func;
} SBlockFunc;
typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int8_t* pIntraPredMode, PDqLayer pCurLayer);
typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
typedef void (*PWelsMapNeighToSample) (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail);
typedef void (*PWelsMap16NeighToSample) (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail);
typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PWelsNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
enum {
OVERWRITE_NONE = 0,
@@ -169,6 +223,7 @@ SLogContext sLogCtx;
void* pArgDec; // structured arguments for decoder, reserved here for extension in the future
SDataBuffer sRawData;
SDataBuffer sSavedData; //for parse only purpose
// Configuration
SDecodingParam* pParam;
@@ -180,6 +235,10 @@ bool bHaveGotMemory; // global memory for decoder context related ever reques
int32_t iImgWidthInPixel; // width of image in pixel reconstruction picture to be output
int32_t iImgHeightInPixel;// height of image in pixel reconstruction picture to be output
int32_t iLastImgWidthInPixel; // width of image in last successful pixel reconstruction picture to be output
int32_t iLastImgHeightInPixel;// height of image in last successful pixel reconstruction picture to be output
bool bFreezeOutput;
// Derived common elements
SNalUnitHeader sCurNalHead;
@@ -202,6 +261,8 @@ struct {
int8_t (*pRefIndex[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM];
int8_t* pLumaQp[LAYER_NUM_EXCHANGEABLE]; /*mb luma_qp*/
int8_t* pChromaQp[LAYER_NUM_EXCHANGEABLE]; /*mb chroma_qp*/
int16_t (*pMvd[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM][MV_A]; //[LAYER_NUM_EXCHANGEABLE MB_BLOCK4x4_NUM*]
uint8_t *pCbfDc[LAYER_NUM_EXCHANGEABLE];
int8_t (*pNzc[LAYER_NUM_EXCHANGEABLE])[24];
int8_t (*pNzcRs[LAYER_NUM_EXCHANGEABLE])[24];
int16_t (*pScaledTCoeff[LAYER_NUM_EXCHANGEABLE])[MB_COEFF_LIST_SIZE]; /*need be aligned*/
@@ -287,6 +348,14 @@ bool bNewSeqBegin;
bool bNextNewSeqBegin;
int iOverwriteFlags;
ERROR_CON_IDC eErrorConMethod; //
//for Parse only
bool bParseOnly;
SSpsBsInfo sSpsBsInfo [MAX_SPS_COUNT];
SSpsBsInfo sSubsetSpsBsInfo [MAX_PPS_COUNT];
SPpsBsInfo sPpsBsInfo [MAX_PPS_COUNT];
SParserBsInfo* pParserBsInfo;
PPicture pPreviousDecodedPictureInDpb; //pointer to previously decoded picture in DPB for error concealment
PGetIntraPredFunc pGetI16x16LumaPredFunc[7]; //h264_predict_copy_16x16;
PGetIntraPredFunc pGetI4x4LumaPredFunc[14]; // h264_predict_4x4_t
@@ -308,8 +377,8 @@ int32_t iCurSeqIntervalMaxPicWidth;
int32_t iCurSeqIntervalMaxPicHeight;
PWelsFillNeighborMbInfoIntra4x4Func pFillInfoCacheIntra4x4Func;
PWelsParseIntra4x4ModeFunc pParseIntra4x4ModeFunc;
PWelsParseIntra16x16ModeFunc pParseIntra16x16ModeFunc;
PWelsMapNeighToSample pMap4x4NeighToSampleFunc;
PWelsMap16NeighToSample pMap16x16NeighToSampleFunc;
//feedback whether or not have VCL in current AU, and the temporal ID
int32_t iFeedbackVclNalInAu;
@@ -325,7 +394,15 @@ void* pTraceHandle;
//Save the last nal header info
SNalUnitHeaderExt sLastNalHdrExt;
SSliceHeader sLastSliceHeader;
SWelsCabacCtx sWelsCabacContexts[4][WELS_QP_MAX + 1][WELS_CONTEXT_COUNT];
bool bCabacInited;
SWelsCabacCtx pCabacCtx[WELS_CONTEXT_COUNT];
PWelsCabacDecEngine pCabacDecEngine;
double dDecTime;
SDecoderStatistics sDecoderStatistics;// For real time debugging
int32_t iECMVs[16][2];
PPicture pECRefPic[16];
unsigned long long uiTimeStamp;
} SWelsDecoderContext, *PWelsDecoderContext;
static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
@@ -337,6 +414,7 @@ for (int i = 0; i < MAX_LAYER_NUM; i++) {
//}
//#endif//__cplusplus
} // namespace WelsDec
#endif//WELS_DECODER_FRAMEWORK_H__

View File

@@ -180,7 +180,9 @@ EER_INFO_INVALID_MMCO_LONG2UNUSED,
ERR_INFO_INVALID_MMCO_SHOART2LONG,
ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW,
ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH,
ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX
ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX,
//for CABAC
ERR_CABAC_NO_BS_TO_READ,
};
//-----------------------------------------------------------------------------------------------------------

View File

@@ -39,6 +39,7 @@
#ifndef WELS_ERROR_CONCEALMENT_H__
#define WELS_ERROR_CONCEALMENT_H__
#include "typedefs.h"
#include "rec_mb.h"
#include "decoder_context.h"
namespace WelsDec {
@@ -48,6 +49,10 @@ void InitErrorCon (PWelsDecoderContext pCtx);
void DoErrorConFrameCopy (PWelsDecoderContext pCtx);
//Do error concealment using slice copy method
void DoErrorConSliceCopy (PWelsDecoderContext pCtx);
//Do error concealment using slice MV copy method
void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32_t iMbXy, int32_t iMbX, int32_t iMbY, sMCRefMember* pMCRefMem, int32_t iCurrPoc);
void GetAvilInfoFromCorrectMb (PWelsDecoderContext pCtx);
void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx);
//Mark erroneous frame as Ref Pic into DPB
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx);
//Judge if EC is needed to current frame

View File

@@ -69,7 +69,11 @@ int32_t iLeftType;
int32_t iTopType;
int32_t iLeftTopType;
int32_t iRightTopType;
} SNeighAvail, *PNeighAvail;
int8_t iTopCbp;
int8_t iLeftCbp;
int8_t iDummy[2]; //for align
} SWelsNeighAvail, *PWelsNeighAvail;
} // namespace WelsDec

View File

@@ -57,7 +57,7 @@ union {
} sVclNal;
SPrefixNalUnit sPrefixNal;
} sNalData;
unsigned long long uiTimeStamp;
} SNalUnit, *PNalUnit;
///////////////////////////////////ACCESS Unit level///////////////////////////////////

View File

@@ -0,0 +1,72 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \file parse_mb_syn_cabac.h
*
* \brief cabac parse for syntax elements
*
* \date 10/10/2014 Created
*
*************************************************************************************
*/
#ifndef WELS_PARSE_MB_SYN_CABAC_H__
#define WELS_PARSE_MB_SYN_CABAC_H__
#include "decoder_context.h"
#include "cabac_decoder.h"
namespace WelsDec {
int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal);
int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip);
int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType);
int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal);
int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal);
int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]);
int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
int8_t ref_idx[LIST_A][30],
int32_t iListIdx, int32_t index, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal);
int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal);
int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta);
int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t index, int32_t iResProperty,
PWelsDecoderContext pCtx, uint32_t& uiCbpBit);
int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
uint32_t& uiBinVal);
int32_t ParseSignificantCoeffCabac (int32_t* significant, int32_t iResProperty, PWelsDecoderContext pCtx);
int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
int32_t index, int32_t iMaxNumCoeff, const uint8_t* pScanTable, int32_t iResProperty, int16_t* sTCoeff, uint8_t uiQp,
PWelsDecoderContext pCtx);
int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx);
}
//#pragma pack()
#endif

View File

@@ -49,101 +49,19 @@
namespace WelsDec {
#define I16_LUMA_DC 1
#define I16_LUMA_AC 2
#define LUMA_DC_AC 3
#define CHROMA_DC 4
#define CHROMA_AC 5
typedef struct TagReadBitsCache {
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
} SReadBitsCache;
#define SHIFT_BUFFER(pBitsCache) { pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits)); }
#define POP_BUFFER(pBitsCache, iCount) { pBitsCache->uiCache32Bit <<= iCount; pBitsCache->uiRemainBits -= iCount; }
static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
};
typedef struct TagI16PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
} SI16PredInfo;
static const SI16PredInfo g_ksI16PredInfo[4] = {
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
};
static const SI16PredInfo g_ksChromaPredInfo[4] = {
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
};
typedef struct TagI4PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
// int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
} SI4PredInfo;
static const SI4PredInfo g_ksI4PredInfo[9] = {
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
};
static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47}; //reference to JM
typedef struct TagPartMbInfo {
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
} SPartMbInfo;
static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
};
static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
};
void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer);
void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer);
void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer);
void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer);
void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
void WelsFillCacheInterCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
/*!
* \brief check iPredMode for intra16x16 eligible or not
* \param input : current iPredMode
@@ -190,19 +108,7 @@ int32_t WelsResidualBlockCavlc (SVlcTable* pVlcTable,
PWelsDecoderContext pCtx);
/*!
* \brief parsing intra mode
* \param input : current mb, bit-stream
* \param output: 0 indicating decoding correctly; -1 means error
*/
int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
/*!
* \brief parsing inter info (including ref_index and mvd)
* \brief parsing inter info (including ref_index and pMvd)
* \param input : decoding context, current mb, bit-stream
* \param output: 0 indicating decoding correctly; -1 means error
*/

View File

@@ -50,6 +50,9 @@ int32_t iLinesize[4];// linesize of picture planes respectively used currently
int32_t iPlanes; // How many planes are introduced due to color space format?
// picture information
/*******************************from EC mv copy****************************/
bool bIdrFlag;
/*******************************from other standard syntax****************************/
/*from sps*/
int32_t iWidthInPixel; // picture width in pixel
@@ -74,6 +77,7 @@ int32_t iLongTermFrameIdx; //id for long term ref pic
int32_t iSpsId; //against mosaic caused by cross-IDR interval reference.
int32_t iPpsId;
unsigned long long uiTimeStamp;
} SPicture, *PPicture; // "Picture" declaration is comflict with Mac system
} // namespace WelsDec

View File

@@ -48,6 +48,27 @@
#include "decoder_context.h"
namespace WelsDec {
typedef struct TagMCRefMember {
uint8_t* pDstY;
uint8_t* pDstU;
uint8_t* pDstV;
uint8_t* pSrcY;
uint8_t* pSrcU;
uint8_t* pSrcV;
int32_t iSrcLineLuma;
int32_t iSrcLineChroma;
int32_t iDstLineLuma;
int32_t iDstLineChroma;
int32_t iPicWidth;
int32_t iPicHeight;
} sMCRefMember;
void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]);
void WelsFillRecNeededMbInfo (PWelsDecoderContext pCtx, bool bOutput, PDqLayer pCurLayer);
@@ -63,9 +84,6 @@ int32_t RecChroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLeve
void GetInterPred (uint8_t* pPredY, uint8_t* pPredCb, uint8_t* pPredCr, PWelsDecoderContext pCtx);
void FillBufForMc (uint8_t* pBuf, int32_t iBufStride, uint8_t* pSrc, int32_t iSrcStride, int32_t iSrcOffset,
int32_t iBlockWidth, int32_t iBlockHeight, int32_t iSrcX, int32_t iSrcY, int32_t iPicWidth, int32_t iPicHeight);
} // namespace WelsDec
#endif //WELS_REC_MB_H__

View File

@@ -120,6 +120,7 @@ PSps pSps;
PPps pPps;
int32_t iSpsId;
int32_t iPpsId;
bool bIdrFlag;
/*********************got from other layer for efficency if possible*********************/
SRefPicListReorderSyn pRefPicListReordering; // Reference picture list reordering syntaxs
@@ -197,6 +198,7 @@ bool bSliceHeaderExtFlag; // Indicate which slice header is used, avc or ext?
/*from lower layer: slice header*/
uint8_t eSliceType;
uint8_t uiPadding[2];
int32_t iLastDeltaQp;
} SSlice, *PSlice;
} // namespace WelsDec

View File

@@ -47,6 +47,11 @@ namespace WelsDec {
extern const uint8_t g_kuiScan8[24];
extern const uint8_t g_kuiLumaDcZigzagScan[16];
extern const uint8_t g_kuiChromaDcScan[4];
extern const uint8_t g_kMbNonZeroCountIdx[24];
extern const uint8_t g_kCacheNzcScanIdx[4*4+4+4+3];
extern const uint8_t g_kCache26ScanIdx[16];
extern const uint8_t g_kCache30ScanIdx[16];
extern const uint8_t g_kNonZeroScanIdxC[4];
/* Profile IDC */
typedef uint8_t ProfileIdc;
enum {
@@ -118,7 +123,94 @@ typedef int32_t SubMbType;
#define IS_I_BL(type) ( (type) == MB_TYPE_INTRA_BL )
#define IS_SUB8x8(type) (MB_TYPE_8x8 == (type) || MB_TYPE_8x8_REF0 == (type))
#define I16_LUMA_DC 1
#define I16_LUMA_AC 2
#define LUMA_DC_AC 3
#define CHROMA_DC 4
#define CHROMA_AC 5
#define CHROMA_DC_U 6
#define CHROMA_DC_V 7
#define CHROMA_AC_U 8
#define CHROMA_AC_V 9
typedef struct TagReadBitsCache {
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
} SReadBitsCache;
#define SHIFT_BUFFER(pBitsCache) { pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits)); }
#define POP_BUFFER(pBitsCache, iCount) { pBitsCache->uiCache32Bit <<= iCount; pBitsCache->uiRemainBits -= iCount; }
static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
};
typedef struct TagI16PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
} SI16PredInfo;
static const SI16PredInfo g_ksI16PredInfo[4] = {
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
};
static const SI16PredInfo g_ksChromaPredInfo[4] = {
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
};
typedef struct TagI4PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
// int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
} SI4PredInfo;
static const SI4PredInfo g_ksI4PredInfo[9] = {
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
};
static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47};
typedef struct TagPartMbInfo {
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
} SPartMbInfo;
static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
};
static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
};
} // namespace WelsDec

View File

@@ -96,4 +96,10 @@
#define MAX_ACCESS_UNIT_CAPACITY 7077888 //Maximum AU size in bytes for level 5.2 for single frame
#define MAX_MACROBLOCK_CAPACITY 5000 //Maximal legal MB capacity, 15000 bits is enough
enum {
BASE_MB = 0,
NON_AVC_REWRITE_ENHANCE_MB =1,
AVC_REWRITE_ENHANCE_MB = 2
};
#endif//WELS_CONSTANCE_H__

View File

@@ -43,7 +43,8 @@
#include "error_code.h"
#include "memmgr_nal_unit.h"
#include "decoder_core.h"
#include "decoder_core.h"
#include "bit_stream.h"
#include "mem_align.h"
namespace WelsDec {
/*!
@@ -111,6 +112,7 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
bool bExtensionFlag = false;
int32_t iErr = ERR_NONE;
int32_t iBitSize = 0;
SDataBuffer* pSavedData = &pCtx->sSavedData;
SLogContext* pLogCtx = & (pCtx->sLogCtx);
pNalUnitHeader->eNalUnitType = NAL_UNIT_UNSPEC_0;//SHOULD init it. because pCtx->sCurNalHead is common variable.
@@ -185,6 +187,7 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
case NAL_UNIT_PREFIX:
pCurNal = &pCtx->sPrefixNal;
pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
if (iNalSize < NAL_UNIT_HEADER_EXT_SIZE) {
PAccessUnit pCurAu = pCtx->pAccessUnitList;
@@ -227,14 +230,18 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc = pNalUnitHeader->uiNalRefIdc;
pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType = pNalUnitHeader->eNalUnitType;
if (pNalUnitHeader->uiNalRefIdc != 0) {
pBs = &pCtx->sBs;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
pBs = &pCtx->sBs;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
InitBits (pBs, pNal, iBitSize);
ParsePrefixNalUnit (pCtx, pBs);
iErr = InitBits (pBs, pNal, iBitSize);
if (iErr) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: InitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
ParsePrefixNalUnit (pCtx, pBs);
}
pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = true;
break;
@@ -250,7 +257,7 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
pCtx->iErrorCode |= dsOutOfMemory;
return NULL;
}
pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc = pNalUnitHeader->uiNalRefIdc;
pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType = pNalUnitHeader->eNalUnitType;
@@ -293,9 +300,28 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
iNalSize -= NAL_UNIT_HEADER_EXT_SIZE;
*pConsumedBytes += NAL_UNIT_HEADER_EXT_SIZE;
if (pCtx->bParseOnly) {
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
pCurNal->sNalData.sVclNal.iNalLength = iSrcNalLen - NAL_UNIT_HEADER_EXT_SIZE;
if (pCurNal->sNalHeaderExt.bIdrFlag) {
* (pSrcNal + 3) &= 0xE0;
* (pSrcNal + 3) |= 0x05;
} else {
* (pSrcNal + 3) &= 0xE0;
* (pSrcNal + 3) |= 0x01;
}
memcpy (pSavedData->pCurPos, pSrcNal, 4);
pSavedData->pCurPos += 4;
memcpy (pSavedData->pCurPos, pSrcNal + 7, iSrcNalLen - 7);
pSavedData->pCurPos += iSrcNalLen - 7;
}
} else {
if (pCtx->bParseOnly) {
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
pCurNal->sNalData.sVclNal.iNalLength = iSrcNalLen;
memcpy (pSavedData->pCurPos, pSrcNal, iSrcNalLen);
pSavedData->pCurPos += iSrcNalLen;
}
if (NAL_UNIT_PREFIX == pCtx->sPrefixNal.sNalHeaderExt.sNalUnitHeader.eNalUnitType) {
if (pCtx->sPrefixNal.sNalData.sPrefixNal.bPrefixNalCorrectFlag) {
PrefetchNalHeaderExtSyntax (pCtx, pCurNal, &pCtx->sPrefixNal);
@@ -309,7 +335,17 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
InitBits (pBs, pNal, iBitSize);
iErr = InitBits (pBs, pNal, iBitSize);
if (iErr) {
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
pCtx->bAuReadyFlag = true;
}
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: InitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag);
if (iErr != ERR_NONE) {
if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { //IDR parse error
@@ -488,7 +524,8 @@ bool CheckNextAuNewSeq (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const
*
*************************************************************************************
*/
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen) {
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen, uint8_t* pSrcNal,
const int32_t kSrcNalLen) {
PBitStringAux pBs = NULL;
EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; // make initial value as unspecified
int32_t iPicWidth = 0;
@@ -505,9 +542,17 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
switch (eNalType) {
case NAL_UNIT_SPS:
case NAL_UNIT_SUBSET_SPS:
if (iBitSize > 0)
InitBits (pBs, pRbsp, iBitSize);
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight);
if (iBitSize > 0) {
iErr = InitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight, pSrcNal, kSrcNalLen);
if (ERR_NONE != iErr) { // modified for pSps/pSubsetSps invalid, 12/1/2009
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
@@ -519,9 +564,17 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
break;
case NAL_UNIT_PPS:
if (iBitSize > 0)
InitBits (pBs, pRbsp, iBitSize);
iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs);
if (iBitSize > 0) {
iErr = InitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs, pSrcNal, kSrcNalLen);
if (ERR_NONE != iErr) { // modified for pps invalid, 12/1/2009
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
@@ -690,6 +743,8 @@ int32_t DecodeSpsSvcExt (PWelsDecoderContext pCtx, PSubsetSps pSpsExt, PBitStrin
const SLevelLimits* GetLevelLimits (int32_t iLevelIdx, bool bConstraint3) {
switch (iLevelIdx) {
case 9:
return &g_ksLevelLimits[1];
case 10:
return &g_ksLevelLimits[0];
case 11:
@@ -736,6 +791,14 @@ bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps) {
if (pCtx->pActiveLayerSps[i] == pSps)
return true;
}
// Pre-active, will be used soon
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->bSpsAvailFlags[pSps->iSpsId]
&& pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
PSps pNextUsedSps =
pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
if (pNextUsedSps->iSpsId == pSps->iSpsId)
return true;
}
return false;
}
@@ -764,7 +827,8 @@ bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps) {
*************************************************************************************
*/
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight) {
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight,
uint8_t* pSrcNal, const int32_t kSrcNalLen) {
PBitStringAux pBs = pBsAux;
SSubsetSps sTempSubsetSps;
PSps pSps = NULL;
@@ -964,6 +1028,79 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //vui_parameters_present_flag
pSps->bVuiParamPresentFlag = !!uiCode;
if (pCtx->bParseOnly) {
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //sps bs exceeds!
pCtx->iErrorCode |= dsOutOfMemory;
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
}
if (!kbUseSubsetFlag) { //SPS
SSpsBsInfo* pSpsBs = &pCtx->sSpsBsInfo [iSpsId];
pSpsBs->iSpsId = iSpsId;
memcpy (pSpsBs->pSpsBsBuf, pSrcNal, kSrcNalLen);
pSpsBs->uiSpsBsLen = (uint32_t) kSrcNalLen;
} else { //subset SPS
SSpsBsInfo* pSpsBs = &pCtx->sSubsetSpsBsInfo [iSpsId];
pSpsBs->iSpsId = iSpsId;
pSpsBs->pSpsBsBuf [0] = pSpsBs->pSpsBsBuf [1] = pSpsBs->pSpsBsBuf [2] = 0x00;
pSpsBs->pSpsBsBuf [3] = 0x01;
pSpsBs->pSpsBsBuf [4] = 0x67;
//re-write subset SPS to SPS
SBitStringAux sSubsetSpsBs;
uint8_t* pBsBuf = static_cast<uint8_t*> (WelsMalloc (SPS_PPS_BS_SIZE + 4,
"Temp buffer for parse only usage.")); //to reserve 4 bytes for UVLC writing buffer
if (NULL == pBsBuf) {
pCtx->iErrorCode |= dsOutOfMemory;
return pCtx->iErrorCode;
}
DecInitBitsForEncoding (&sSubsetSpsBs, pBsBuf, (int32_t) (pBs->pEndBuf - pBs->pStartBuf));
DecBsWriteBits (&sSubsetSpsBs, 8, 77); //profile_idc, forced to Main profile
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet0Flag); // constraint_set0_flag
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet1Flag); // constraint_set1_flag
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet2Flag); // constraint_set2_flag
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet3Flag); // constraint_set3_flag
DecBsWriteBits (&sSubsetSpsBs, 4, 0); //constraint_set4_flag, constraint_set5_flag, reserved_zero_2bits
DecBsWriteBits (&sSubsetSpsBs, 8, pSps->uiLevelIdc); //level_idc
DecBsWriteUe (&sSubsetSpsBs, pSps->iSpsId); //sps_id
DecBsWriteUe (&sSubsetSpsBs, pSps->uiLog2MaxFrameNum - 4); //log2_max_frame_num_minus4
DecBsWriteUe (&sSubsetSpsBs, pSps->uiPocType); //pic_order_cnt_type
if (pSps->uiPocType == 0) {
DecBsWriteUe (&sSubsetSpsBs, pSps->iLog2MaxPocLsb - 4); //log2_max_pic_order_cnt_lsb_minus4
} else if (pSps->uiPocType == 1) {
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bDeltaPicOrderAlwaysZeroFlag); //delta_pic_order_always_zero_flag
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForNonRefPic); //offset_for_no_ref_pic
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForTopToBottomField); //offset_for_top_to_bottom_field
DecBsWriteUe (&sSubsetSpsBs, pSps->iNumRefFramesInPocCycle); //num_ref_frames_in_pic_order_cnt_cycle
for (int32_t i = 0; i < pSps->iNumRefFramesInPocCycle; ++i) {
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForRefFrame[i]); //offset_for_ref_frame[i]
}
}
DecBsWriteUe (&sSubsetSpsBs, pSps->iNumRefFrames); //max_num_ref_frames
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bGapsInFrameNumValueAllowedFlag); //gaps_in_frame_num_value_allowed_flag
DecBsWriteUe (&sSubsetSpsBs, pSps->iMbWidth - 1); //pic_width_in_mbs_minus1
DecBsWriteUe (&sSubsetSpsBs, pSps->iMbHeight - 1); //pic_height_in_map_units_minus1
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bFrameMbsOnlyFlag); //frame_mbs_only_flag
if (!pSps->bFrameMbsOnlyFlag) {
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bMbaffFlag); //mb_adaptive_frame_field_flag
}
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bDirect8x8InferenceFlag); //direct_8x8_inference_flag
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bFrameCroppingFlag); //frame_cropping_flag
if (pSps->bFrameCroppingFlag) {
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iLeftOffset); //frame_crop_left_offset
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iRightOffset); //frame_crop_right_offset
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iTopOffset); //frame_crop_top_offset
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iBottomOffset); //frame_crop_bottom_offset
}
DecBsWriteOneBit (&sSubsetSpsBs, 0); //vui_parameters_present_flag
DecBsRbspTrailingBits (&sSubsetSpsBs); //finished, rbsp trailing bit
int32_t iRbspSize = (int32_t) (sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf);
RBSP2EBSP (pSpsBs->pSpsBsBuf + 5, sSubsetSpsBs.pStartBuf, iRbspSize);
pSpsBs->uiSpsBsLen = (uint16_t) (sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf + 5);
if (pBsBuf) {
WelsFree (pBsBuf, "pBsBuf for parse only usage");
}
}
}
// Check if SPS SVC extension applicated
if (kbUseSubsetFlag && (PRO_SCALABLE_BASELINE == uiProfileIdc || PRO_SCALABLE_HIGH == uiProfileIdc)) {
if (DecodeSpsSvcExt (pCtx, pSubsetSps, pBs) != ERR_NONE) {
@@ -1049,7 +1186,8 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
* \note Call it in case eNalUnitType is PPS.
*************************************************************************************
*/
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux) {
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal,
const int32_t kSrcNalLen) {
PPps pPps = NULL;
SPps sTempPps;
@@ -1163,6 +1301,16 @@ int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux)
memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
pCtx->bPpsAvailFlags[uiPpsId] = true;
}
if (pCtx->bParseOnly) {
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //pps bs exceeds
pCtx->iErrorCode |= dsOutOfMemory;
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
}
SPpsBsInfo* pPpsBs = &pCtx->sPpsBsInfo [uiPpsId];
pPpsBs->iPpsId = (int32_t) uiPpsId;
memcpy (pPpsBs->pPpsBsBuf, pSrcNal, kSrcNalLen);
pPpsBs->uiPpsBsLen = kSrcNalLen;
}
return ERR_NONE;
}

View File

@@ -38,6 +38,7 @@
*************************************************************************************
*/
#include "bit_stream.h"
#include "error_code.h"
namespace WelsDec {
@@ -47,10 +48,14 @@ inline uint32_t GetValue4Bytes (uint8_t* pDstNal) {
return uiValue;
}
void InitReadBits (PBitStringAux pBitString) {
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset) {
if (pBitString->pCurBuf >= (pBitString->pEndBuf - iEndOffset)) {
return ERR_INFO_INVALID_ACCESS;
}
pBitString->uiCurBits = GetValue4Bytes (pBitString->pCurBuf);
pBitString->pCurBuf += 4;
pBitString->iLeftBits = -16;
return ERR_NONE;
}
/*!
@@ -60,23 +65,154 @@ void InitReadBits (PBitStringAux pBitString) {
* \param kpBuf bit-stream buffer
* \param kiSize size in bits for decoder; size in bytes for encoder
*
* \return size of buffer data in byte; failed in -1 return
* \return 0: success, other: fail
*/
int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize) {
const int32_t kiSizeBuf = (kiSize + 7) >> 3;
uint8_t* pTmp = (uint8_t*)kpBuf;
if (NULL == pTmp)
return -1;
return ERR_INFO_INVALID_ACCESS;
pBitString->pStartBuf = pTmp; // buffer to start position
pBitString->pEndBuf = pTmp + kiSizeBuf; // buffer + length
pBitString->iBits = kiSize; // count bits of overall bitstreaming inputindex;
pBitString->pCurBuf = pBitString->pStartBuf;
InitReadBits (pBitString);
int32_t iErr = InitReadBits (pBitString, 0);
if (iErr) {
return iErr;
}
return ERR_NONE;
}
return kiSizeBuf;
//Following for write bs in decoder
void DecInitBitsForEncoding (PBitStringAux pBitString, uint8_t* pBuf, const int32_t kiSize) {
uint8_t* pPtr = pBuf;
pBitString->pStartBuf = pPtr;
pBitString->pCurBuf = pPtr;
pBitString->pEndBuf = pPtr + kiSize;
pBitString->iLeftBits = 32;
pBitString->uiCurBits = 0;
}
#define WRITE_BE_32(ptr, val) do { \
(ptr)[0] = (val) >> 24; \
(ptr)[1] = (val) >> 16; \
(ptr)[2] = (val) >> 8; \
(ptr)[3] = (val) >> 0; \
} while (0);
int32_t DecBsWriteBits (PBitStringAux pBitString, int32_t iLen, const uint32_t kuiValue) {
if (iLen < pBitString->iLeftBits) {
pBitString->uiCurBits = (pBitString->uiCurBits << iLen) | kuiValue;
pBitString->iLeftBits -= iLen;
} else {
iLen -= pBitString->iLeftBits;
pBitString->uiCurBits = (pBitString->uiCurBits << pBitString->iLeftBits) | (kuiValue >> iLen);
WRITE_BE_32 (pBitString->pCurBuf, pBitString->uiCurBits);
pBitString->pCurBuf += 4;
pBitString->uiCurBits = kuiValue & ((1 << iLen) - 1);
pBitString->iLeftBits = 32 - iLen;
}
return 0;
}
int32_t DecBsWriteOneBit (PBitStringAux pBitString, const uint32_t kuiValue) {
DecBsWriteBits (pBitString, 1, kuiValue);
return 0;
}
int32_t DecBsFlush (PBitStringAux pBitString) {
WRITE_BE_32 (pBitString->pCurBuf, pBitString->uiCurBits << pBitString->iLeftBits);
pBitString->pCurBuf += 4 - pBitString->iLeftBits / 8;
pBitString->iLeftBits = 32;
pBitString->uiCurBits = 0;
return 0;
}
const uint32_t g_kuiDecGolombUELength[256] = {
1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, //14
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //30
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,//46
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,//62
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,//
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
17
};
int32_t DecBsWriteUe (PBitStringAux pBitString, const uint32_t kuiValue) {
uint32_t iTmpValue = kuiValue + 1;
if (256 > kuiValue) {
DecBsWriteBits (pBitString, g_kuiDecGolombUELength[kuiValue], kuiValue + 1);
} else {
uint32_t n = 0;
if (iTmpValue & 0xffff0000) {
iTmpValue >>= 16;
n += 16;
}
if (iTmpValue & 0xff) {
iTmpValue >>= 8;
n += 8;
}
//n += (g_kuiDecGolombUELength[iTmpValue] >> 1);
n += (g_kuiDecGolombUELength[iTmpValue - 1] >> 1);
DecBsWriteBits (pBitString, (n << 1) + 1, kuiValue + 1);
}
return 0;
}
int32_t DecBsWriteSe (PBitStringAux pBitString, const int32_t kiValue) {
uint32_t iTmpValue;
if (0 == kiValue) {
DecBsWriteOneBit (pBitString, 1);
} else if (0 < kiValue) {
iTmpValue = (kiValue << 1) - 1;
DecBsWriteUe (pBitString, iTmpValue);
} else {
iTmpValue = ((-kiValue) << 1);
DecBsWriteUe (pBitString, iTmpValue);
}
return 0;
}
int32_t DecBsRbspTrailingBits (PBitStringAux pBitString) {
DecBsWriteOneBit (pBitString, 1);
DecBsFlush (pBitString);
return 0;
}
void RBSP2EBSP (uint8_t* pDstBuf, uint8_t* pSrcBuf, const int32_t kiSize) {
uint8_t* pSrcPointer = pSrcBuf;
uint8_t* pDstPointer = pDstBuf;
uint8_t* pSrcEnd = pSrcBuf + kiSize;
int32_t iZeroCount = 0;
while (pSrcPointer < pSrcEnd) {
if (iZeroCount == 2 && *pSrcPointer <= 3) {
//add the code 0x03
*pDstPointer++ = 3;
iZeroCount = 0;
}
if (*pSrcPointer == 0) {
++ iZeroCount;
} else {
iZeroCount = 0;
}
*pDstPointer++ = *pSrcPointer++;
}
}
} // namespace WelsDec

View File

@@ -0,0 +1,330 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* cabac_decoder.cpp: deals with cabac state transition and related functions
*/
#include "cabac_decoder.h"
namespace WelsDec {
static const int16_t g_kMvdBinPos2Ctx [8] = {0, 1, 2, 3, 3, 3, 3, 3};
void WelsCabacGlobalInit (PWelsDecoderContext pCtx) {
for (int32_t iModel = 0; iModel < 4; iModel++) {
for (int32_t iQp = 0; iQp <= WELS_QP_MAX; iQp++)
for (int32_t iIdx = 0; iIdx < WELS_CONTEXT_COUNT; iIdx++) {
int32_t m = g_kiCabacGlobalContextIdx[iIdx][iModel][0];
int32_t n = g_kiCabacGlobalContextIdx[iIdx][iModel][1];
int32_t iPreCtxState = WELS_CLIP3 ((((m * iQp) >> 4) + n), 1, 126);
uint8_t uiValMps = 0;
uint8_t uiStateIdx = 0;
if (iPreCtxState <= 63) {
uiStateIdx = 63 - iPreCtxState;
uiValMps = 0;
} else {
uiStateIdx = iPreCtxState - 64;
uiValMps = 1;
}
pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiState = uiStateIdx;
pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiMPS = uiValMps;
}
}
pCtx->bCabacInited = true;
}
// ------------------- 1. context initialization
void WelsCabacContextInit (PWelsDecoderContext pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp) {
int32_t iIdx = pCtx->eSliceType == WelsCommon::I_SLICE ? 0 : iCabacInitIdc + 1;
if (!pCtx->bCabacInited) {
WelsCabacGlobalInit (pCtx);
}
memcpy (pCtx->pCabacCtx, pCtx->sWelsCabacContexts[iIdx][iQp],
WELS_CONTEXT_COUNT * sizeof (SWelsCabacCtx));
}
// ------------------- 2. decoding Engine initialization
int32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {
int32_t iRemainingBits = - pBsAux->iLeftBits; //pBsAux->iLeftBits < 0
int32_t iRemainingBytes = (iRemainingBits >> 3) + 2; //+2: indicating the pre-read 2 bytes
uint8_t* pCurr;
pCurr = pBsAux->pCurBuf - iRemainingBytes;
if(pCurr >= (pBsAux->pEndBuf - 1)) {
return ERR_INFO_INVALID_ACCESS;
}
pDecEngine->uiOffset = ((pCurr[0] << 16) | (pCurr[1] << 8) | pCurr[2]);
pDecEngine->uiOffset <<= 16;
pDecEngine->uiOffset |= (pCurr[3] << 8) | pCurr[4];
pDecEngine->iBitsLeft = 31;
pDecEngine->pBuffCurr = pCurr + 5;
pDecEngine->uiRange = WELS_CABAC_HALF;
pDecEngine->pBuffStart = pBsAux->pStartBuf;
pDecEngine->pBuffEnd = pBsAux->pEndBuf;
pBsAux->iLeftBits = 0;
return ERR_NONE;
}
void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {
//CABAC decoding finished, changing to SBitStringAux
pDecEngine->pBuffCurr -= (pDecEngine->iBitsLeft >> 3);
pDecEngine->iBitsLeft = 0; //pcm_alignment_zero_bit in CABAC
pBsAux->iLeftBits = 0;
pBsAux->pStartBuf = pDecEngine->pBuffStart;
pBsAux->pCurBuf = pDecEngine->pBuffCurr;
pBsAux->uiCurBits = 0;
pBsAux->iIndex = 0;
}
// ------------------- 3. actual decoding
int32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead) {
intX_t iLeftBytes = pDecEngine->pBuffEnd - pDecEngine->pBuffCurr;
iNumBitsRead = 0;
uiValue = 0;
if (iLeftBytes <= 0) {
return ERR_CABAC_NO_BS_TO_READ;
}
switch (iLeftBytes) {
case 3:
uiValue = ((pDecEngine->pBuffCurr[0]) << 16 | (pDecEngine->pBuffCurr[1]) << 8 | (pDecEngine->pBuffCurr[2]));
pDecEngine->pBuffCurr += 3;
iNumBitsRead = 24;
break;
case 2:
uiValue = ((pDecEngine->pBuffCurr[0]) << 8 | (pDecEngine->pBuffCurr[1]));
pDecEngine->pBuffCurr += 2;
iNumBitsRead = 16;
break;
case 1:
uiValue = pDecEngine->pBuffCurr[0];
pDecEngine->pBuffCurr += 1;
iNumBitsRead = 8;
break;
default:
uiValue = ((pDecEngine->pBuffCurr[0] << 24) | (pDecEngine->pBuffCurr[1]) << 16 | (pDecEngine->pBuffCurr[2]) << 8 |
(pDecEngine->pBuffCurr[3]));
pDecEngine->pBuffCurr += 4;
iNumBitsRead = 32;
break;
}
return ERR_NONE;
}
int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal) {
int32_t iErrorInfo = ERR_NONE;
uint32_t uiState = pBinCtx->uiState;
uiBinVal = pBinCtx->uiMPS;
uint64_t uiOffset = pDecEngine->uiOffset;
uint64_t uiRange = pDecEngine->uiRange;
int32_t iRenorm = 1;
uint32_t uiRangeLPS = g_kuiCabacRangeLps[uiState][ (uiRange >> 6) & 0x03];
uiRange -= uiRangeLPS;
if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) { //LPS
uiOffset -= (uiRange << pDecEngine->iBitsLeft);
uiBinVal ^= 0x0001;
if (!uiState)
pBinCtx->uiMPS ^= 0x01;
pBinCtx->uiState = g_kuiStateTransTable[uiState][0];
iRenorm = g_kRenormTable256[uiRangeLPS];
uiRange = (uiRangeLPS << iRenorm);
} else { //MPS
pBinCtx->uiState = g_kuiStateTransTable[uiState][1];
if (uiRange >= WELS_CABAC_QUARTER) {
pDecEngine->uiRange = uiRange;
return ERR_NONE;
} else {
uiRange <<= 1;
}
}
//Renorm
pDecEngine->uiRange = uiRange;
pDecEngine->iBitsLeft -= iRenorm;
if (pDecEngine->iBitsLeft > 0) {
pDecEngine->uiOffset = uiOffset;
return ERR_NONE;
}
uint32_t uiVal = 0;
int32_t iNumBitsRead = 0;
iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
pDecEngine->uiOffset = (uiOffset << iNumBitsRead) | uiVal;
pDecEngine->iBitsLeft += iNumBitsRead;
if (iErrorInfo && pDecEngine->iBitsLeft < 0) {
return iErrorInfo;
}
return ERR_NONE;
}
int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {
int32_t iErrorInfo = ERR_NONE;
int32_t iBitsLeft = pDecEngine->iBitsLeft;
uint64_t uiOffset = pDecEngine->uiOffset;
uint64_t uiRangeValue;
if (iBitsLeft <= 0) {
uint32_t uiVal = 0;
int32_t iNumBitsRead = 0;
iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
uiOffset = (uiOffset << iNumBitsRead) | uiVal;
iBitsLeft = iNumBitsRead;
if (iErrorInfo && iBitsLeft == 0) {
return iErrorInfo;
}
}
iBitsLeft--;
uiRangeValue = (pDecEngine->uiRange << iBitsLeft);
if (uiOffset >= uiRangeValue) {
pDecEngine->iBitsLeft = iBitsLeft;
pDecEngine->uiOffset = uiOffset - uiRangeValue;
uiBinVal = 1;
return ERR_NONE;
}
pDecEngine->iBitsLeft = iBitsLeft;
pDecEngine->uiOffset = uiOffset;
uiBinVal = 0;
return ERR_NONE;
}
int32_t DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {
int32_t iErrorInfo = ERR_NONE;
uint64_t uiRange = pDecEngine->uiRange - 2;
uint64_t uiOffset = pDecEngine->uiOffset;
if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) {
uiBinVal = 1;
} else {
uiBinVal = 0;
// Renorm
if (uiRange < WELS_CABAC_QUARTER) {
int32_t iRenorm = g_kRenormTable256[uiRange];
pDecEngine->uiRange = (uiRange << iRenorm);
pDecEngine->iBitsLeft -= iRenorm;
if (pDecEngine->iBitsLeft < 0) {
uint32_t uiVal = 0;
int32_t iNumBitsRead = 0;
iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
pDecEngine->uiOffset = (pDecEngine->uiOffset << iNumBitsRead) | uiVal;
pDecEngine->iBitsLeft += iNumBitsRead;
}
if (iErrorInfo && pDecEngine->iBitsLeft < 0) {
return iErrorInfo;
}
return ERR_NONE;
} else {
pDecEngine->uiRange = uiRange;
return ERR_NONE;
}
}
return ERR_NONE;
}
int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,
uint32_t& uiSymVal) {
uiSymVal = 0;
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiSymVal));
if (uiSymVal == 0) {
return ERR_NONE;
} else {
uint32_t uiCode;
pBinCtx += iCtxOffset;
uiSymVal = 0;
do {
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));
++uiSymVal;
} while (uiCode != 0);
return ERR_NONE;
}
}
int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal) {
uint32_t uiCode;
int32_t iSymTmp = 0;
int32_t iSymTmp2 = 0;
uiSymVal = 0;
do {
WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));
if (uiCode == 1) {
iSymTmp += (1 << iCount);
++iCount;
}
} while (uiCode != 0);
while (iCount--) {
WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));
if (uiCode == 1) {
iSymTmp2 |= (1 << iCount);
}
}
uiSymVal = (uint32_t) (iSymTmp + iSymTmp2);
return ERR_NONE;
}
uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiCode) {
uiCode = 0;
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));
if (uiCode == 0)
return ERR_NONE;
else {
uint32_t uiTmp, uiCount = 1;
uiCode = 0;
do {
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiTmp));
++uiCode;
++uiCount;
} while (uiTmp != 0 && uiCount != 13);
if (uiTmp != 0) {
WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 0, uiTmp));
uiCode += uiTmp + 1;
}
return ERR_NONE;
}
return ERR_NONE;
}
int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxBin, uint32_t& uiCode) {
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[0], uiCode));
if (uiCode == 0)
return ERR_NONE;
else {
uint32_t uiTmp, uiCount = 1;
uiCode = 0;
do {
WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[uiCount++], uiTmp));
uiCode++;
} while (uiTmp != 0 && uiCount != 8);
if (uiTmp != 0) {
WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 3, uiTmp));
uiCode += (uiTmp + 1);
}
return ERR_NONE;
}
}
}

View File

@@ -44,6 +44,7 @@
#include "decode_slice.h"
#include "parse_mb_syn_cavlc.h"
#include "parse_mb_syn_cabac.h"
#include "rec_mb.h"
#include "mv_pred.h"
@@ -318,6 +319,577 @@ void WelsChromaDcIdct (int16_t* pBlock) {
pBlk[iStride1] = (iE - iB) >> 1;
}
void WelsMap4x4NeighToSampleNormal (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail) { //left
pSampleAvail[ 6] =
pSampleAvail[12] =
pSampleAvail[18] =
pSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail) { //top_left
pSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail) { //top
pSampleAvail[1] =
pSampleAvail[2] =
pSampleAvail[3] =
pSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail) { //top_right
pSampleAvail[5] = 1;
}
}
void WelsMap4x4NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) { //left
pSampleAvail[ 6] =
pSampleAvail[12] =
pSampleAvail[18] =
pSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) { //top_left
pSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) { //top
pSampleAvail[1] =
pSampleAvail[2] =
pSampleAvail[3] =
pSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) { //top_right
pSampleAvail[5] = 1;
}
}
void WelsMap16x16NeighToSampleNormal (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail) {
*pSampleAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail) {
*pSampleAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail) {
*pSampleAvail |= 1;
}
}
void WelsMap16x16NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
*pSampleAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
*pSampleAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
*pSampleAvail |= 1;
}
}
int32_t ParseIntra4x4Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode,
PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
int32_t iCode;
pCtx->pMap4x4NeighToSampleFunc (pNeighAvail, iSampleAvail);
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
int32_t iPrevIntra4x4PredMode = 0;
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeLumaCabac (pCtx, iCode));
iPrevIntra4x4PredMode = iCode;
} else {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
iPrevIntra4x4PredMode = uiCode;
}
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
if (iPrevIntra4x4PredMode == -1)
iBestMode = kiPredMode;
else
iBestMode = iPrevIntra4x4PredMode + (iPrevIntra4x4PredMode >= kiPredMode);
} else {
if (iPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else {
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode));
iBestMode = uiCode + ((int32_t) uiCode >= kiPredMode);
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
if (iCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
} else {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
}
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return ERR_NONE;
}
int32_t ParseIntra16x16Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
int32_t iCode;
pCtx->pMap16x16NeighToSampleFunc (pNeighAvail, &uiNeighAvail);
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
if (iCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
} else {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
}
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacISliceBaseMode0 (PWelsDecoderContext pCtx, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBsAux = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SWelsNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t i;
uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
WELS_READ_VERIFY (ParseMBTypeISliceCabac (pCtx, &sNeighAvail, uiMbType));
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
} else if (25 == uiMbType) { //I_PCM
WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
} else if (0 == uiMbType) { //I4x4
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
//get uiCbp for I4x4
WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, &sNeighAvail, uiCbp));
pCurLayer->pCbp[iMbXy] = uiCbp;
pSlice->iLastDeltaQp = uiCbp == 0 ? 0: pSlice->iLastDeltaQp;
uiCbpChroma = uiCbp >> 4;
uiCbpLuma = uiCbp & 15;
} else { //I16x16;
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBsAux, pCurLayer));
}
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
pCurLayer->pCbfDc[iMbXy] = 0;
if (pCurLayer->pCbp[iMbXy] == 0 && IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) {
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
}
if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
int32_t iQpDelta, iId8x8, iId4x4;
WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
if (iQpDelta > 25 || iQpDelta < -26) {//out of iQpDelta range
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
//step1: Luma DC
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
//step2: Luma AC
if (uiCbpLuma) {
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, i,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC,
pCurLayer->pScaledTCoeff[iMbXy] + (i << 4), pCurLayer->pLumaQp[iMbXy], pCtx));
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
} else { //pNonZeroCount = 0
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
}
} else { //non-MB_TYPE_INTRA16x16
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
if (uiCbpLuma & (1 << iId8x8)) {
int32_t iIdx = (iId8x8 << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
//Luma (DC and AC decoding together)
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
pCtx));
iIdx++;
}
} else {
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2)]], 0);
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
}
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
}
//chroma
//step1: DC
if (1 == uiCbpChroma || 2 == uiCbpChroma) {
//Cb Cr
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (0 << 2), 4, g_kuiChromaDcScan,
CHROMA_DC_V, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (0 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (1 << 2), 4, g_kuiChromaDcScan,
CHROMA_DC_U, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (1 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
}
//step2: AC
if (2 == uiCbpChroma) {
for (i = 0; i < 2; i++) { //Cb Cr
int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
int32_t iIdx = 16 + (i << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), iResProperty,
pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
iIdx++;
}
}
ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
} else {
ST16 (&pCurLayer->pNzc[iMbXy][16], 0);
ST16 (&pCurLayer->pNzc[iMbXy][20], 0);
ST16 (&pCurLayer->pNzc[iMbXy][18], 0);
ST16 (&pCurLayer->pNzc[iMbXy][22], 0);
}
} else {
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
}
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
WELS_READ_VERIFY (WelsDecodeMbCabacISliceBaseMode0 (pCtx, uiEosFlag));
return ERR_NONE;
}
int32_t WelsDecodeMbCabacPSliceBaseMode0 (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBsAux = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t i;
uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
WELS_READ_VERIFY (ParseMBTypePSliceCabac (pCtx, pNeighAvail, uiMbType));
// uiMbType = 4 is not allowded.
if (uiMbType < 4) { //Inter mode
int16_t pMotionVector[LIST_A][30][MV_A];
int16_t pMvdCache[LIST_A][30][MV_A];
int8_t pRefIndex[LIST_A][30];
pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
WelsFillCacheInterCabac (pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex, pCurLayer);
WELS_READ_VERIFY (ParseInterMotionInfoCabac (pCtx, pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex));
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
} else { //Intra mode
uiMbType -= 5;
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
}
if (25 == uiMbType) { //I_PCM
WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
} else { //normal Intra mode
if (0 == uiMbType) { //Intra4x4
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (pNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, pNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
} else { //Intra16x16
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, pNeighAvail, pBsAux, pCurLayer));
}
}
}
if (MB_TYPE_INTRA16x16 != pCurLayer->pMbType[iMbXy]) {
WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, pNeighAvail, uiCbp));
pCurLayer->pCbp[iMbXy] = uiCbp;
pSlice->iLastDeltaQp = uiCbp == 0 ? 0: pSlice->iLastDeltaQp;
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
}
pCtx->sBlockFunc.pWelsBlockZero16x16Func (pCurLayer->pScaledTCoeff[iMbXy], 16);
pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256, 8);
pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256 + 64, 8);
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
int32_t iQpDelta, iId8x8, iId4x4;
WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
//step1: Luma DC
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
//step2: Luma AC
if (uiCbpLuma) {
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, i, iScanIdxEnd - WELS_MAX (iScanIdxStart,
1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4),
pCurLayer->pLumaQp[iMbXy], pCtx));
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
} else {
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
}
} else { //non-MB_TYPE_INTRA16x16
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
if (uiCbpLuma & (1 << iId8x8)) {
int32_t iIdx = (iId8x8 << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
//Luma (DC and AC decoding together)
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
pCtx));
iIdx++;
}
} else {
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[iId8x8 << 2]], 0);
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
}
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
}
//chroma
//step1: DC
if (1 == uiCbpChroma || 2 == uiCbpChroma) {
for (i = 0; i < 2; i++) {
int32_t iResProperty = i ? CHROMA_DC_V : CHROMA_DC_U;
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 16 + (i << 2), 4, g_kuiChromaDcScan,
iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
}
}
//step2: AC
if (2 == uiCbpChroma) {
for (i = 0; i < 2; i++) {
int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
int32_t index = 16 + (i << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, index,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1),
iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (index << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
index++;
}
}
ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
} else {
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
}
} else {
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
}
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
uint32_t uiCode;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t i;
SWelsNeighAvail uiNeighAvail;
pCurLayer->pCbp[iMbXy] = 0;
pCurLayer->pCbfDc[iMbXy] = 0;
pCurLayer->pChromaPredMode[iMbXy] = C_PRED_DC;
GetNeighborAvailMbType (&uiNeighAvail, pCurLayer);
WELS_READ_VERIFY (ParseSkipFlagCabac (pCtx, &uiNeighAvail, uiCode));
if (uiCode) {
int16_t pMv[2] = {0};
pCurLayer->pMbType[iMbXy] = MB_TYPE_SKIP;
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
memset (pCurLayer->pRefIndex[0][iMbXy], 0, sizeof (int8_t) * 16);
//predict mv
PredPSkipMvFromNeighbor (pCurLayer, pMv);
for (i = 0; i < 16; i++) {
ST32 (pCurLayer->pMv[0][iMbXy][i], * (uint32_t*)pMv);
ST32 (pCurLayer->pMvd[0][iMbXy][i], 0);
}
if (!pSlice->sSliceHeaderExt.bDefaultResidualPredFlag) {
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (int16_t));
}
//reset rS
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp; //??????????????? dqaunt of previous mb
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
//for neighboring CABAC usage
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
return ERR_NONE;
}
WELS_READ_VERIFY (WelsDecodeMbCabacPSliceBaseMode0 (pCtx, &uiNeighAvail, uiEosFlag));
return ERR_NONE;
}
int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PFmo pFmo = pCtx->pFmo;
@@ -329,34 +901,50 @@ int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNal
PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader;
int32_t iMbX, iMbY;
const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice
PBitStringAux pBs = pCurLayer->pBitStringAux;
intX_t iUsedBits = 0;
PWelsDecMbCavlcFunc pDecMbCavlcFunc;
uint32_t uiEosFlag = 0;
PWelsDecMbFunc pDecMbFunc;
pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding.
if (P_SLICE == pSliceHeader->eSliceType) {
pDecMbCavlcFunc = WelsDecodeMbCavlcPSlice;
} else { //I_SLICE
pDecMbCavlcFunc = WelsDecodeMbCavlcISlice;
if (pCtx->pPps->bEntropyCodingModeFlag) {
if (pSlice->sSliceHeaderExt.bAdaptiveMotionPredFlag ||
pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag ||
pSlice->sSliceHeaderExt.bAdaptiveResidualPredFlag) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"WelsDecodeSlice()::::ILP flag exist, not supported with CABAC enabled!");
pCtx->iErrorCode |= dsBitstreamError;
return dsBitstreamError;
}
if (P_SLICE == pSliceHeader->eSliceType)
pDecMbFunc = WelsDecodeMbCabacPSlice;
else //I_SLICE. B_SLICE not supported now
pDecMbFunc = WelsDecodeMbCabacISlice;
} else {
if (P_SLICE == pSliceHeader->eSliceType) {
pDecMbFunc = WelsDecodeMbCavlcPSlice;
} else { //I_SLICE
pDecMbFunc = WelsDecodeMbCavlcISlice;
}
}
if (pSliceHeader->pPps->bConstainedIntraPredFlag) {
pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain1Intra4x4;
pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain1;
pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain1;
pCtx->pMap4x4NeighToSampleFunc = WelsMap4x4NeighToSampleConstrain1;
pCtx->pMap16x16NeighToSampleFunc = WelsMap16x16NeighToSampleConstrain1;
} else {
pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain0Intra4x4;
pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain0;
pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain0;
pCtx->pMap4x4NeighToSampleFunc = WelsMap4x4NeighToSampleNormal;
pCtx->pMap16x16NeighToSampleFunc = WelsMap16x16NeighToSampleNormal;
}
pCtx->eSliceType = pSliceHeader->eSliceType;
if (pCurLayer->sLayerInfo.pPps->bEntropyCodingModeFlag == 1) {
//CABAC encoding is unsupported yet!
return -1;
int32_t iQp = pSlice->sSliceHeaderExt.sSliceHeader.iSliceQp;
int32_t iCabacInitIdc = pSlice->sSliceHeaderExt.sSliceHeader.iCabacInitIdc;
WelsCabacContextInit (pCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
//InitCabacCtx (pCtx->pCabacCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux));
}
iNextMbXyIndex = pSliceHeader->iFirstMbInSlice;
@@ -398,31 +986,21 @@ int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNal
}
pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc;
iRet = pDecMbCavlcFunc (pCtx, pNalCur);
iRet = pDecMbFunc (pCtx, pNalCur, uiEosFlag);
if (iRet != ERR_NONE) {
return iRet;
}
++pSlice->iTotalMbInCurSlice;
if (uiEosFlag) { //end of slice
break;
}
if (pSliceHeader->pPps->uiNumSliceGroups > 1) {
iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
} else {
++iNextMbXyIndex;
}
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
if (iUsedBits == pBs->iBits && 0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun) { // slice boundary
break;
}
if (iUsedBits > pBs->iBits) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeSlice()::::pBs incomplete, iUsedBits:%" PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
iMbX = iNextMbXyIndex % pCurLayer->iMbWidth;
iMbY = iNextMbXyIndex / pCurLayer->iMbWidth;
pCurLayer->iMbX = iMbX;
@@ -440,7 +1018,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SNeighAvail sNeighAvail;
SWelsNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
@@ -455,11 +1033,11 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
int32_t iCode;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
uiMbType = uiCode;
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
@@ -508,20 +1086,18 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
}
pBs->pCurBuf += 384;
InitReadBits (pBs);
//step 3: update QP and pNonZeroCount
pCurLayer->pLumaQp[iMbXy] = 0;
pCurLayer->pChromaQp[iMbXy] = 0;
memset (pNzc, 16, sizeof (pCurLayer->pNzc[iMbXy])); //Rec. 9.2.1 for PCM, nzc=16
WELS_READ_VERIFY(InitReadBits (pBs, 0));
return 0;
} else if (0 == uiMbType) { //reference to JM
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
return -1;
}
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer));
//uiCbp
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //coded_block_pattern
@@ -542,9 +1118,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
return -1;
}
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer));
}
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
@@ -572,19 +1146,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
//refer to JVT-X201wcm1.doc equation(7-35)
if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
if (pCurLayer->pLumaQp[iMbXy] < 0) {
pCurLayer->pLumaQp[iMbXy] += 52;
} else {
pCurLayer->pLumaQp[iMbXy] -= 52;
}
}
//QP should be in the range of [0, 51]
if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0,
@@ -673,14 +1235,14 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
return 0;
}
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBs = pCurLayer->pBitStringAux;
PSliceHeaderExt pSliceHeaderExt = &pCurLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt;
int32_t iBaseModeFlag;
int32_t iRet = 0; //should have the return value to indicate decoding error or not, It's NECESSARY--2010.4.15
uint32_t uiCode;
intX_t iUsedBits;
if (pSliceHeaderExt->bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
@@ -698,6 +1260,19 @@ int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
return iRet;
}
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
// sub 1, for stop bit
if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) { // slice boundary
uiEosFlag = 1;
}
if (iUsedBits > (pBs->iBits -
1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
return 0;
}
@@ -708,11 +1283,10 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
SWelsNeighAvail sNeighAvail;
int32_t iMbX = pCurLayer->iMbX;
int32_t iMbY = pCurLayer->iMbY;
const int32_t iMbXy = pCurLayer->iMbXyIndex;
@@ -721,15 +1295,13 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
uint32_t uiMbType = 0, uiCbp = 0, uiCbpL = 0, uiCbpC = 0;
uint32_t uiCode;
int32_t iCode;
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;//2009.10.23
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
uiMbType = uiCode;
if (uiMbType < 5) { //inter MB type
int16_t iMotionVector[LIST_A][30][MV_A];
int8_t iRefIndex[LIST_A][30];
pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
WelsFillCacheInter (&sNeighAvail, pNonZeroCount, iMotionVector, iRefIndex, pCurLayer);
@@ -800,7 +1372,6 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
}
pBs->pCurBuf += 384;
InitReadBits (pBs);
//step 3: update QP and pNonZeroCount
pCurLayer->pLumaQp[iMbXy] = 0;
@@ -812,13 +1383,14 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
ST32A4 (&pNzc[12], 0x10101010);
ST32A4 (&pNzc[16], 0x10101010);
ST32A4 (&pNzc[20], 0x10101010);
WELS_READ_VERIFY (InitReadBits (pBs, 0));
return 0;
} else {
if (0 == uiMbType) {
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
if (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
return -1;
}
} else { //I_PCM exclude, we can ignore it
@@ -828,7 +1400,7 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
if (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer)) {
return -1;
}
}
@@ -877,19 +1449,7 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
//refer to JVT-X201wcm1.doc equation(7-35)
if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
if (pCurLayer->pLumaQp[iMbXy] < 0) {
pCurLayer->pLumaQp[iMbXy] += 52;
} else {
pCurLayer->pLumaQp[iMbXy] -= 52;
}
}
//QP should be in the range of [0, 51]
if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0,
@@ -978,12 +1538,12 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
return 0;
}
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBs = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
intX_t iUsedBits;
const int32_t iMbXy = pCurLayer->iMbXyIndex;
int8_t* pNzc = pCurLayer->pNzc[iMbXy];
int32_t iBaseModeFlag, i;
@@ -996,7 +1556,6 @@ int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
if (-1 == pSlice->iMbSkipRun) {
return -1;
}
}
if (pSlice->iMbSkipRun--) {
int16_t iMv[2];
@@ -1031,27 +1590,37 @@ int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
}
pCurLayer->pCbp[iMbXy] = 0;
return 0;
}
if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
} else {
iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
} else {
iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
}
if (!iBaseModeFlag) {
iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
iBaseModeFlag);
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
}
if (iRet) { //occur error when parsing, MUST STOP decoding
return iRet;
}
}
if (!iBaseModeFlag) {
iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
iBaseModeFlag);
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
// sub 1, for stop bit
if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) { // slice boundary
uiEosFlag = 1;
}
if (iRet) { //occur error when parsing, MUST STOP decoding
return iRet;
if (iUsedBits > (pBs->iBits -
1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
return 0;
}
@@ -1069,6 +1638,31 @@ void WelsBlockFuncInit (SBlockFunc* pFunc, int32_t iCpu) {
pFunc->pWelsSetNonZeroCountFunc = SetNonZeroCount_AArch64_neon;
}
#endif
pFunc->pWelsBlockZero16x16Func = WelsBlockZero16x16_c;
pFunc->pWelsBlockZero8x8Func = WelsBlockZero8x8_c;
//TO DO add neon and X86
#ifdef HAVE_NEON
if (iCpu & WELS_CPU_NEON) {
pFunc->pWelsBlockZero16x16Func = WelsBlockZero16x16_neon;
pFunc->pWelsBlockZero8x8Func = WelsBlockZero8x8_neon;
}
#endif
#ifdef HAVE_NEON_AARCH64
if (iCpu & WELS_CPU_NEON) {
pFunc->pWelsBlockZero16x16Func = WelsBlockZero16x16_AArch64_neon;
pFunc->pWelsBlockZero8x8Func = WelsBlockZero8x8_AArch64_neon;
}
#endif
#if defined(X86_ASM)
if (iCpu & WELS_CPU_SSE2) {
pFunc->pWelsBlockZero16x16Func = WelsBlockZero16x16_sse2;
pFunc->pWelsBlockZero8x8Func = WelsBlockZero8x8_sse2;
}
#endif
}
void SetNonZeroCount_c (int8_t* pNonZeroCount) {
@@ -1079,4 +1673,21 @@ void SetNonZeroCount_c (int8_t* pNonZeroCount) {
}
}
void WelsBlockInit (int16_t* pBlock, int iW, int iH, int iStride, uint8_t uiVal) {
int32_t i;
int16_t* pDst = pBlock;
for (i = 0; i < iH; i++) {
memset (pDst, uiVal, iW * sizeof (int16_t));
pDst += iStride;
}
}
void WelsBlockZero16x16_c (int16_t* pBlock, int32_t iStride) {
WelsBlockInit (pBlock, 16, 16, iStride, 0);
}
void WelsBlockZero8x8_c (int16_t* pBlock, int32_t iStride) {
WelsBlockInit (pBlock, 8, 8, iStride, 0);
}
} // namespace WelsDec

View File

@@ -139,12 +139,15 @@ void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
pCtx->uiCpuFlag = 0;
pCtx->bAuReadyFlag = 0; // au data is not ready
pCtx->bCabacInited = false;
pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0; // alloc picture data when picture size is available
pCtx->iLastImgWidthInPixel = 0;
pCtx->iLastImgHeightInPixel = 0;
pCtx->bFreezeOutput = false;
pCtx->iFrameNum = -1;
pCtx->iPrevFrameNum = -1;
@@ -160,7 +163,7 @@ void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
pCtx->pPicBuff[LIST_1] = NULL;
pCtx->bAvcBasedFlag = true;
pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY;
pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
pCtx->pPreviousDecodedPictureInDpb = NULL;
}
@@ -241,6 +244,10 @@ int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const
pCtx->bHaveGotMemory = true; // global memory for decoder context related is requested
pCtx->pDec = NULL; // need prefetch a new pic due to spatial size changed
if (pCtx->pCabacDecEngine == NULL)
pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) WelsMalloc (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
return ERR_NONE;
}
@@ -266,8 +273,11 @@ void WelsFreeMem (PWelsDecoderContext pCtx) {
// added for safe memory
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0;
pCtx->iLastImgWidthInPixel = 0;
pCtx->iLastImgHeightInPixel = 0;
pCtx->bFreezeOutput = false;
pCtx->bHaveGotMemory = false;
WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
}
/*!
@@ -340,6 +350,9 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
return iRet;
pCtx->eErrorConMethod = pCtx->pParam->eEcActiveIdc;
if (pCtx->bParseOnly) //parse only, disable EC method
pCtx->eErrorConMethod = ERROR_CON_DISABLE;
if (VIDEO_BITSTREAM_SVC == pCtx->pParam->sVideoProperty.eVideoBsType ||
VIDEO_BITSTREAM_AVC == pCtx->pParam->sVideoProperty.eVideoBsType) {
pCtx->eVideoType = pCtx->pParam->sVideoProperty.eVideoBsType;
@@ -364,7 +377,7 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
* \note N/A
*************************************************************************************
*/
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx) {
if (pCtx == NULL) {
return ERR_INFO_INVALID_PTR;
}
@@ -372,6 +385,7 @@ int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
// default
WelsDecoderDefaults (pCtx, pLogCtx);
pCtx->bParseOnly = bParseOnly;
// open decoder
return WelsOpenDecoder (pCtx);
}
@@ -417,9 +431,10 @@ void GetVclNalTemporalId (PWelsDecoderContext pCtx) {
*************************************************************************************
*/
int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
uint8_t** ppDst, SBufferInfo* pDstBufInfo) {
uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo) {
if (!pCtx->bEndOfStreamFlag) {
SDataBuffer* pRawData = &pCtx->sRawData;
SDataBuffer* pSavedData = NULL;
int32_t iSrcIdx = 0; //the index of source bit-stream till now after parsing one or more NALs
int32_t iSrcConsumed = 0; // consumed bit count of source bs
@@ -447,7 +462,12 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
pRawData->pCurPos = pRawData->pHead;
}
if (pCtx->bParseOnly) {
pSavedData = &pCtx->sSavedData;
if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) {
pSavedData->pCurPos = pSavedData->pHead;
}
}
//copy raw data from source buffer (application) to raw data buffer (codec inside)
//0x03 removal and extract all of NAL Unit from current raw data
pDstNal = pRawData->pCurPos;
@@ -464,12 +484,14 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
} else {
iConsumedBytes = 0;
pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
0; // set 4 reserved bytes to zero
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
}
if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
}
if (pCtx->bAuReadyFlag) {
ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
@@ -480,9 +502,6 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
if ((pCtx->eErrorConMethod == ERROR_CON_DISABLE) || (dsOutOfMemory & pCtx->iErrorCode))
ResetParameterSetsState (pCtx);
if (dsOutOfMemory & pCtx->iErrorCode) {
return pCtx->iErrorCode;
}
@@ -496,19 +515,16 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
if ((pCtx->eErrorConMethod == ERROR_CON_DISABLE) || (dsOutOfMemory & pCtx->iErrorCode))
ResetParameterSetsState (pCtx);
}
return pCtx->iErrorCode;
}
pDstNal += iDstIdx; //update current position
pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL
if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) {
pRawData->pCurPos = pRawData->pHead;
pDstNal = pRawData->pCurPos = pRawData->pHead;
} else {
pRawData->pCurPos = pDstNal;
}
pDstNal = pRawData->pCurPos + 4; //init, 4 bytes used to store the next NAL
pSrcNal += iSrcIdx + 3;
iSrcConsumed += 3;
@@ -524,12 +540,14 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
//last NAL decoding
iConsumedBytes = 0;
pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
0; // set 4 reserved bytes to zero
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
}
if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
}
if (pCtx->bAuReadyFlag) {
ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
@@ -540,8 +558,6 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
if ((pCtx->eErrorConMethod == ERROR_CON_DISABLE) || (dsOutOfMemory & pCtx->iErrorCode))
ResetParameterSetsState (pCtx);
return pCtx->iErrorCode;
}
}
@@ -553,12 +569,10 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
ResetParameterSetsState (pCtx);
}
return pCtx->iErrorCode;
}
pDstNal += iDstIdx;
pRawData->pCurPos = pDstNal; //init the pCurPos for next NAL(s) storage
pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
} else { /* no supplementary picture payload input, but stored a picture */
PAccessUnit pCurAu =
pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization
@@ -576,8 +590,6 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
if ((pCtx->eErrorConMethod == ERROR_CON_DISABLE) || (dsOutOfMemory & pCtx->iErrorCode))
ResetParameterSetsState (pCtx);
return pCtx->iErrorCode;
}
}

View File

@@ -66,7 +66,7 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) {
pCtx->bPrintFrameErrorTraceFlag = true;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
"DecodeFrameConstruction()::::output first frame of new sequence, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d, ignored error packet:%d.",
"DecodeFrameConstruction(): will output first frame of new sequence, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d, ignored error packet:%d.",
kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset,
pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount);
pCtx->iIgnoredErrorInfoPacketCount = 0;
@@ -75,7 +75,7 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ",
"DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ",
pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight);
bFrameCompleteFlag = false; //return later after output buffer is done
if (pCtx->bInstantDecFlag) //no-delay decoding, wait for new slice
@@ -83,35 +83,60 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
} else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag
&& (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done
pCtx->pDec->bIsComplete = true;
pCtx->bFreezeOutput = false;
}
pCtx->iTotalNumMbRec = 0;
//////output:::normal path
ppDst[0] = pPic->pData[0];
ppDst[1] = pPic->pData[1];
ppDst[2] = pPic->pData[2];
if (!pCtx->bParseOnly) {
//////output:::normal path
pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
ppDst[0] = pPic->pData[0];
ppDst[1] = pPic->pData[1];
ppDst[2] = pPic->pData[2];
pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
pDstInfo->iBufferStatus = 1;
pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
pDstInfo->iBufferStatus = 1;
}
bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth)
|| (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight);
pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth;
pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight;
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
&& pPic->bIsComplete); // When EC disable, ECed picture not output
else if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE
|| pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
&& pCtx->iErrorCode && bOutResChange)
pCtx->bFreezeOutput = true;
if ((pDstInfo->iBufferStatus == 1) && (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag)) {
if (pPic->bIsComplete)
pCtx->sDecoderStatistics.uiIDRRecvNum++;
else
pCtx->sDecoderStatistics.uiEcIDRNum++;
}
if (pDstInfo->iBufferStatus == 0) {
if (!bFrameCompleteFlag)
pCtx->iErrorCode |= dsBitstreamError;
return -1;
}
if (pCtx->bFreezeOutput) {
pDstInfo->iBufferStatus = 0;
if (pCtx->bNewSeqBegin) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction():New sequence detected, but freezed.");
}
}
return 0;
}
@@ -131,13 +156,6 @@ inline void HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal
if (0 == pCurNal->sNalHeaderExt.uiTemporalId) {
pCtx->bReferenceLostAtT0Flag = true;
}
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) {
#ifndef LONG_TERM_REF
if (pCtx->bReferenceLostAtT0Flag) {
ResetParameterSetsState (pCtx);
}
#endif
}
pCtx->iErrorCode |= dsBitstreamError;
}
@@ -145,13 +163,6 @@ inline void HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal)
if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) {
pCtx->bReferenceLostAtT0Flag = true;
}
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) {
#ifndef LONG_TERM_REF
if (pCtx->bReferenceLostAtT0Flag) {
ResetParameterSetsState (pCtx);
}
#endif
}
pCtx->iErrorCode |= dsRefLost;
}
@@ -314,6 +325,14 @@ int32_t InitBsBuffer (PWelsDecoderContext pCtx) {
}
pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead;
pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte;
if (pCtx->bParseOnly) {
if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (WelsMalloc (pCtx->iMaxBsBufferSizeInByte,
"pCtx->sSavedData.pHead"))) == NULL) {
return ERR_INFO_OUT_OF_MEMORY;
}
pCtx->sSavedData.pStartPos = pCtx->sSavedData.pCurPos = pCtx->sSavedData.pHead;
pCtx->sSavedData.pEnd = pCtx->sSavedData.pHead + pCtx->iMaxBsBufferSizeInByte;
}
return ERR_NONE;
}
@@ -386,6 +405,9 @@ int32_t WelsInitMemory (PWelsDecoderContext pCtx) {
pCtx->bEndOfStreamFlag = false;
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0;
pCtx->iLastImgWidthInPixel = 0;
pCtx->iLastImgHeightInPixel = 0;
pCtx->bFreezeOutput = false;
return ERR_NONE;
}
@@ -414,6 +436,13 @@ void WelsFreeMemory (PWelsDecoderContext pCtx) {
pCtx->sRawData.pEnd = NULL;
pCtx->sRawData.pStartPos = NULL;
pCtx->sRawData.pCurPos = NULL;
if (pCtx->sSavedData.pHead) {
WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead");
}
pCtx->sSavedData.pHead = NULL;
pCtx->sSavedData.pEnd = NULL;
pCtx->sSavedData.pStartPos = NULL;
pCtx->sSavedData.pCurPos = NULL;
}
/*
@@ -584,6 +613,7 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
pSliceHeadExt->pSubsetSps = pSubsetSps;
bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag);
pSliceHead->bIdrFlag = bIdrFlag;
if (pSps->uiLog2MaxFrameNum == 0) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "non existing SPS referenced");
@@ -707,8 +737,11 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
}
if (pPps->bEntropyCodingModeFlag) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): CABAC in Enhancement layer not supported.");
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_CABAC_EL);
if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
pSliceHead->iCabacInitIdc = uiCode;
} else
pSliceHead->iCabacInitIdc = 0;
}
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_qp_delta
@@ -971,6 +1004,8 @@ int32_t UpdateAccessUnit (PWelsDecoderContext pCtx) {
}
if (uiActualIdx ==
pCurAu->uiActualUnitsNum) { // no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009
pCtx->sDecoderStatistics.uiIDRLostNum++;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU.");
pCtx->iErrorCode |= dsRefLost;
@@ -1021,6 +1056,10 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
"pCtx->sMb.pLumaQp[]");
pCtx->sMb.pChromaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t),
"pCtx->sMb.pChromaQp[]");
pCtx->sMb.pMvd[i][0] = (int16_t (*)[16][2])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (
int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]");
pCtx->sMb.pCbfDc[i] = (uint8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint8_t),
"pCtx->sMb.pCbfDc[]");
pCtx->sMb.pNzc[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
"pCtx->sMb.pNzc[]");
pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
@@ -1057,6 +1096,8 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
(NULL == pCtx->sMb.pRefIndex[i][0]) ||
(NULL == pCtx->sMb.pLumaQp[i]) ||
(NULL == pCtx->sMb.pChromaQp[i]) ||
(NULL == pCtx->sMb.pMvd[i][0]) ||
(NULL == pCtx->sMb.pCbfDc[i]) ||
(NULL == pCtx->sMb.pNzc[i]) ||
(NULL == pCtx->sMb.pNzcRs[i]) ||
(NULL == pCtx->sMb.pScaledTCoeff[i]) ||
@@ -1076,7 +1117,6 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
++ i;
} while (i < LAYER_NUM_EXCHANGEABLE);
pCtx->bInitialDqLayersMem = true;
pCtx->iPicWidthReq = kiMaxWidth;
pCtx->iPicHeightReq = kiMaxHeight;
@@ -1124,6 +1164,16 @@ void UninitialDqLayersContext (PWelsDecoderContext pCtx) {
pCtx->sMb.pChromaQp[i] = NULL;
}
if (pCtx->sMb.pMvd[i][0]) {
WelsFree (pCtx->sMb.pMvd[i][0], "pCtx->sMb.pMvd[][]");
pCtx->sMb.pMvd[i][0] = NULL;
}
if (pCtx->sMb.pCbfDc[i]) {
WelsFree (pCtx->sMb.pCbfDc[i], "pCtx->sMb.pCbfDc[]");
pCtx->sMb.pCbfDc[i] = NULL;
}
if (pCtx->sMb.pNzc[i]) {
WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]");
@@ -1652,7 +1702,8 @@ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferI
if (ERR_NONE != iErr) {
ForceResetCurrentAccessUnit (pCtx->pAccessUnitList);
pDstInfo->iBufferStatus = 0;
if (!pCtx->bParseOnly)
pDstInfo->iBufferStatus = 0;
return iErr;
}
@@ -1673,6 +1724,54 @@ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferI
iErr = DecodeCurrentAccessUnit (pCtx, ppDst, pDstInfo);
if (pCtx->bParseOnly) {
if (dsErrorFree == pCtx->iErrorCode) {
SParserBsInfo* pParser = pCtx->pParserBsInfo;
uint8_t* pDstBuf = pParser->pDstBuff;
SNalUnit* pCurNal = NULL;
int32_t iNalLen = 0;
int32_t iIdx = pCurAu->uiStartPos;
int32_t iEndIdx = pCurAu->uiEndPos;
uint8_t* pNalBs = NULL;
pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0;
pParser->iNalNum = 0;
pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4);
pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4);
if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR
bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType);
SSpsBsInfo* pSpsBs = NULL;
SPpsBsInfo* pPpsBs = NULL;
int32_t iSpsId = pCtx->pSps->iSpsId;
int32_t iPpsId = pCtx->pPps->iPpsId;
pCtx->bParamSetsLostFlag = false;
//find required sps, pps and write into dst buff
pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId];
memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen);
pParser->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen;
pDstBuf += pSpsBs->uiSpsBsLen;
pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen);
pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen;
pDstBuf += pPpsBs->uiPpsBsLen;
} //IDR required SPS, PPS
//then VCL data re-write
while (iIdx <= iEndIdx) {
pCurNal = pCurAu->pNalUnitsList [iIdx ++];
iNalLen = pCurNal->sNalData.sVclNal.iNalLength;
pNalBs = pCurNal->sNalData.sVclNal.pNalPos;
pParser->iNalLenInByte [pParser->iNalNum ++] = iNalLen;
memcpy (pDstBuf, pNalBs, iNalLen);
pDstBuf += iNalLen;
}
} else { //error
pCtx->pParserBsInfo->uiOutBsTimeStamp = 0;
pCtx->pParserBsInfo->iNalNum = 0;
pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
}
}
WelsDecodeAccessUnitEnd (pCtx);
pCtx->bNewSeqBegin = false;
@@ -1754,6 +1853,8 @@ void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) {
pCurDq->pRefIndex[0] = pCtx->sMb.pRefIndex[0][0];
pCurDq->pLumaQp = pCtx->sMb.pLumaQp[0];
pCurDq->pChromaQp = pCtx->sMb.pChromaQp[0];
pCurDq->pMvd[0] = pCtx->sMb.pMvd[0][0];
pCurDq->pCbfDc = pCtx->sMb.pCbfDc[0];
pCurDq->pNzc = pCtx->sMb.pNzc[0];
pCurDq->pNzcRs = pCtx->sMb.pNzcRs[0];
pCurDq->pScaledTCoeff = pCtx->sMb.pScaledTCoeff[0];
@@ -1768,14 +1869,6 @@ void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) {
}
}
// added to reset state of parameter sets to waiting successive incoming IDR, 6/4/2010
// It will be called in case packets lost/ broken and decoded failed at temporal level 0
void ResetParameterSetsState (PWelsDecoderContext pCtx) {
pCtx->bSpsExistAheadFlag = false;
pCtx->bSubspsExistAheadFlag = false;
pCtx->bPpsExistAheadFlag = false;
}
/*
* DecodeCurrentAccessUnit
* Decode current access unit when current AU is completed.
@@ -1826,6 +1919,7 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
return ERR_INFO_REF_COUNT_OVERFLOW;
}
}
pCtx->pDec->uiTimeStamp = pNalCur->uiTimeStamp;
if (pCtx->iTotalNumMbRec == 0) { //Picture start to decode
for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i)
@@ -1855,6 +1949,8 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
memcpy (&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); //confirmed_safe_unsafe_usage
pCtx->pDec->iFrameNum = pSh->iFrameNum;
pCtx->pDec->iFramePoc = pSh->iPicOrderCntLsb; // still can not obtain correct, because current do not support POCtype 2
pCtx->pDec->bIdrFlag = pNalCur->sNalHeaderExt.bIdrFlag;
memcpy (&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof (SSliceHeaderExt)); //confirmed_safe_unsafe_usage
pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag = pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag;
@@ -1910,7 +2006,6 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
#else
pCtx->bReferenceLostAtT0Flag = true;
#endif
ResetParameterSetsState (pCtx);
return ERR_INFO_REFERENCE_PIC_LOST;
}
}
@@ -1943,10 +2038,13 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
return iRet;
}
}
if (bReconstructSlice) {
if (WelsDecodeConstructSlice (pCtx, pNalCur)) {
pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false
return -1;
if (!pCtx->bParseOnly) {
if (bReconstructSlice) {
if (WelsDecodeConstructSlice (pCtx, pNalCur)) {
pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false
return -1;
}
}
}
if (bAllRefComplete && (pCtx->sRefPic.uiRefCount[LIST_0] > 0 || pCtx->eSliceType != I_SLICE)) {
@@ -1989,20 +2087,21 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
#endif//#if !CODEC_FOR_TESTBED
if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) {
if (!pCtx->bInstantDecFlag) {
//Do error concealment here
if ((NeedErrorCon (pCtx)) && (pCtx->eErrorConMethod != ERROR_CON_DISABLE)) {
ImplementErrorCon (pCtx);
pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
if (!pCtx->bParseOnly) {
if (!pCtx->bInstantDecFlag) {
//Do error concealment here
if ((NeedErrorCon (pCtx)) && (pCtx->eErrorConMethod != ERROR_CON_DISABLE)) {
ImplementErrorCon (pCtx);
pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
}
}
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
return ERR_NONE;
}
}
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
return ERR_NONE;
}
if (uiNalRefIdc > 0) {
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for EC
iRet = WelsMarkAsRef (pCtx);
@@ -2016,6 +2115,10 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
pCtx->pDec->iLinesize,
pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
pCtx->pDec = NULL;
} else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR
|| pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) {
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for MV Copy EC
pCtx->pDec = NULL;
}
}
@@ -2046,6 +2149,9 @@ bool CheckAndFinishLastPic (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferIn
if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use
MarkECFrameAsRef (pCtx);
} else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR
|| pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) {
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future MV Copy use
}
} else {
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo))

View File

@@ -54,6 +54,56 @@ const uint8_t g_kuiScan4[16] = { //for mb cache in sMb (only current element, wi
// extern at wels_common_basis.h
/*common use table*/
const uint8_t g_kMbNonZeroCountIdx[24] = {
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 1, 4, 5, // 2 3 | 6 7 0 | 1 0 1 2 3
2, 3, 6, 7, //--------------- --------- 4 5 6 7
8, 9, 12, 13, // 8 9 | 12 13 2 | 3 8 9 10 11
10, 11, 14, 15, // 10 11 | 14 15-----------------------------> 12 13 14 15
16, 17, 20, 21, //---------------- chroma 8*8 block 16 17 18 19
18, 19, 22, 23 // 16 17 | 20 21 0 1 20 21 22 23
};
//cache element equal to 26
const uint8_t g_kCacheNzcScanIdx[4 * 4 + 4 + 4 + 3] = {
/* Luma */
9, 10, 17, 18, // 1+1*8, 2+1*8, 1+2*8, 2+2*8,
11, 12, 19, 20, // 3+1*8, 4+1*8, 3+2*8, 4+2*8,
25, 26, 33, 34, // 1+3*8, 2+3*8, 1+4*8, 2+4*8,
27, 28, 35, 36, // 3+3*8, 4+3*8, 3+4*8, 4+4*8,
/* Cb */
14, 15, // 6+1*8, 7+1*8,
22, 23, // 6+2*8, 7+2*8,
/* Cr */
38, 39, // 6+4*8, 7+4*8,
46, 47, // 6+5*8, 7+5*8,
/* Luma DC */
41, // 1+5*8
/* Chroma DC */
42, 43 // 2+5*8, 3+5*8,
};
const uint8_t g_kCache26ScanIdx[16] = { //intra4*4_pred_mode and pNonZeroCount cache scan index, 4*4 block as basic unit
6, 7, 11, 12,
8, 9, 13, 14,
16, 17, 21, 22,
18, 19, 23, 24
};
//cache element equal to 30
const uint8_t g_kCache30ScanIdx[16] = { //mv or pRefIndex cache scan index, 4*4 block as basic unit
7, 8, 13, 14,
9, 10, 15, 16,
19, 20, 25, 26,
21, 22, 27, 28
};
const uint8_t g_kNonZeroScanIdxC[4] = { //pNonZeroCount cache for chroma, 4*4 block as basic unit
4, 5,
7, 8
};
const uint8_t g_kuiScan8[24] = { // [16 + 2*4]
9, 10, 17, 18, // 1+1*8, 2+1*8, 1+2*8, 2+2*8,
11, 12, 19, 20, // 3+1*8, 4+1*8, 3+2*8, 4+2*8,

View File

@@ -41,7 +41,10 @@
namespace WelsDec {
//Init
void InitErrorCon (PWelsDecoderContext pCtx) {
if (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) {
if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR)
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR)
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE)) {
pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_c;
pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
@@ -79,6 +82,8 @@ void DoErrorConFrameCopy (PWelsDecoderContext pCtx) {
uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
int32_t iStrideY = pDstPic->iLinesize[0];
int32_t iStrideUV = pDstPic->iLinesize[1];
if ((pCtx->eErrorConMethod == ERROR_CON_FRAME_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
if (pSrcPic == NULL) { //no ref pic, assign specific data to picture
memset (pDstPic->pData[0], 128, uiHeightInPixelY * iStrideY);
memset (pDstPic->pData[1], 128, (uiHeightInPixelY >> 1) * iStrideUV);
@@ -97,10 +102,13 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
PPicture pDstPic = pCtx->pDec;
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
//uint8_t *pDstData[3], *pSrcData[3];
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
int32_t iMbEcedNum = 0;
//Do slice copy late
int32_t iMbXyIndex;
uint8_t* pSrcData, *pDstData;
@@ -110,6 +118,7 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
iMbXyIndex = iMbY * iMbWidth + iMbX;
if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
iMbEcedNum++;
if (pSrcPic != NULL) {
iSrcStride = pSrcPic->iLinesize[0];
//Y component
@@ -147,8 +156,268 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
} //iMbX
} //iMbY
pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+ ((iMbEcedNum * 100) / iMbNum) ;
}
//Do error concealment using slice MV copy method
void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32_t iMbXy, int32_t iMbX, int32_t iMbY,
sMCRefMember* pMCRefMem) {
int16_t iMVs[2];
int32_t iMbXInPix = iMbX << 4;
int32_t iMbYInPix = iMbY << 4;
int32_t iScale0;
int32_t iScale1;
uint8_t* pDst[3];
int32_t iCurrPoc = pDec->iFramePoc;
pDst[0] = pDec->pData[0] + iMbXInPix + iMbYInPix * pMCRefMem->iDstLineLuma;
pDst[1] = pDec->pData[1] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
pDst[2] = pDec->pData[2] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
if (pDec->bIdrFlag == true || pCtx->pECRefPic[0] == NULL) {
uint8_t* pSrcData;
//Y component
pSrcData = pMCRefMem->pSrcY + iMbY * 16 * pMCRefMem->iSrcLineLuma + iMbX * 16;
pCtx->sCopyFunc.pCopyLumaFunc (pDst[0], pMCRefMem->iDstLineLuma, pSrcData, pMCRefMem->iSrcLineLuma);
//U component
pSrcData = pMCRefMem->pSrcU + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
pCtx->sCopyFunc.pCopyChromaFunc (pDst[1], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
//V component
pSrcData = pMCRefMem->pSrcV + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
pCtx->sCopyFunc.pCopyChromaFunc (pDst[2], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
return;
}
if (pCtx->pECRefPic[0]) {
if (pCtx->pECRefPic[0] == pRef) {
iMVs[0] = pCtx->iECMVs[0][0];
iMVs[1] = pCtx->iECMVs[0][1];
} else {
iScale0 = pCtx->pECRefPic[0]->iFramePoc - iCurrPoc;
iScale1 = pRef->iFramePoc - iCurrPoc;
iMVs[0] = pCtx->iECMVs[0][0] * iScale1 / iScale0;
iMVs[1] = pCtx->iECMVs[0][1] * iScale1 / iScale0;
}
pMCRefMem->pDstY = pDst[0];
pMCRefMem->pDstU = pDst[1];
pMCRefMem->pDstV = pDst[2];
int32_t iFullMVx = (iMbXInPix << 2) + iMVs[0]; //quarter pixel
int32_t iFullMVy = (iMbYInPix << 2) + iMVs[1];
// only use to be output pixels to EC;
int32_t iPicWidthLeftLimit = 0;
int32_t iPicHeightTopLimit = 0;
int32_t iPicWidthRightLimit = pMCRefMem->iPicWidth;
int32_t iPicHeightBottomLimit = pMCRefMem->iPicHeight;
if (pCtx->pSps->bFrameCroppingFlag) {
iPicWidthLeftLimit = 0 + pCtx->sFrameCrop.iLeftOffset * 2;
iPicWidthRightLimit = (pMCRefMem->iPicWidth - pCtx->sFrameCrop.iRightOffset * 2);
iPicHeightTopLimit = 0 + pCtx->sFrameCrop.iTopOffset * 2;
iPicHeightBottomLimit = (pMCRefMem->iPicHeight - pCtx->sFrameCrop.iTopOffset * 2);
}
// further make sure no need to expand picture
int32_t iMinLeftOffset = (iPicWidthLeftLimit + 2) << 2;
int32_t iMaxRightOffset = ((iPicWidthRightLimit - 19) << 2);
int32_t iMinTopOffset = (iPicHeightTopLimit + 2) << 2;
int32_t iMaxBottomOffset = ((iPicHeightBottomLimit - 19) << 2);
if (iFullMVx < iMinLeftOffset) {
iFullMVx = (iFullMVx >> 2) << 2;
iFullMVx = WELS_MAX (iPicWidthLeftLimit, iFullMVx);
} else if (iFullMVx > iMaxRightOffset) {
iFullMVx = (iFullMVx >> 2) << 2;
iFullMVx = WELS_MIN (((iPicWidthRightLimit - 17) << 2), iFullMVx);
}
if (iFullMVy < iMinTopOffset) {
iFullMVy = (iFullMVy >> 2) << 2;
iFullMVy = WELS_MAX (iPicHeightTopLimit, iFullMVy);
} else if (iFullMVy > iMaxBottomOffset) {
iFullMVy = (iFullMVy >> 2) << 2;
iFullMVy = WELS_MIN (((iPicHeightBottomLimit - 17) << 2), iFullMVy);
}
iMVs[0] = iFullMVx - (iMbXInPix << 2);
iMVs[1] = iFullMVy - (iMbYInPix << 2);
BaseMC (pMCRefMem, iMbXInPix, iMbYInPix, &pCtx->sMcFunc, 16, 16, iMVs);
}
return ;
}
void GetAvilInfoFromCorrectMb (PWelsDecoderContext pCtx) {
int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
int32_t iInterMbCorrectNum[16];
int32_t iMbXyIndex;
int8_t iRefIdx;
memset (pCtx->iECMVs, 0, sizeof (int32_t) * 32);
memset (pCtx->pECRefPic, 0, sizeof (PPicture) * 16);
memset (iInterMbCorrectNum, 0, sizeof (int32_t) * 16);
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
iMbXyIndex = iMbY * iMbWidth + iMbX;
if (pMbCorrectlyDecodedFlag[iMbXyIndex] && IS_INTER (pCurDqLayer->pMbType[iMbXyIndex])) {
int32_t iMBType = pCurDqLayer->pMbType[iMbXyIndex];
switch (iMBType) {
case MB_TYPE_SKIP:
case MB_TYPE_16x16:
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
iInterMbCorrectNum[iRefIdx]++;
break;
case MB_TYPE_16x8:
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
iInterMbCorrectNum[iRefIdx]++;
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][8];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][8][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][8][1];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
iInterMbCorrectNum[iRefIdx]++;
break;
case MB_TYPE_8x16:
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
iInterMbCorrectNum[iRefIdx]++;
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][2];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][2][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][2][1];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
iInterMbCorrectNum[iRefIdx]++;
break;
case MB_TYPE_8x8:
case MB_TYPE_8x8_REF0: {
uint32_t iSubMBType;
int32_t i, j, iIIdx, iJIdx;
for (i = 0; i < 4; i++) {
iSubMBType = pCurDqLayer->pSubMbType[iMbXyIndex][i];
iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][iIIdx];
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
switch (iSubMBType) {
case SUB_MB_TYPE_8x8:
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
iInterMbCorrectNum[iRefIdx]++;
break;
case SUB_MB_TYPE_8x4:
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 4][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 4][1];
iInterMbCorrectNum[iRefIdx] += 2;
break;
case SUB_MB_TYPE_4x8:
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 1][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 1][1];
iInterMbCorrectNum[iRefIdx] += 2;
break;
case SUB_MB_TYPE_4x4: {
for (j = 0; j < 4; j++) {
iJIdx = ((j >> 1) << 2) + (j & 1);
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + iJIdx][0];
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + iJIdx][1];
}
iInterMbCorrectNum[iRefIdx] += 4;
}
break;
default:
break;
}
}
}
break;
default:
break;
}
} //pMbCorrectlyDecodedFlag[iMbXyIndex]
} //iMbX
} //iMbY
for (int32_t i = 0; i < 16; i++) {
if (iInterMbCorrectNum[i]) {
pCtx->iECMVs[i][0] = pCtx->iECMVs[i][0] / iInterMbCorrectNum[i];
pCtx->iECMVs[i][1] = pCtx->iECMVs[i][1] / iInterMbCorrectNum[i];
}
}
}
void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx) {
int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
PPicture pDstPic = pCtx->pDec;
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
int32_t iMbEcedNum = 0;
int32_t iMbXyIndex;
uint8_t* pDstData;
uint32_t iDstStride = pDstPic->iLinesize[0];
sMCRefMember sMCRefMem;
if (pSrcPic != NULL) {
sMCRefMem.iSrcLineLuma = pSrcPic->iLinesize[0];
sMCRefMem.iSrcLineChroma = pSrcPic->iLinesize[1];
sMCRefMem.pSrcY = pSrcPic->pData[0];
sMCRefMem.pSrcU = pSrcPic->pData[1];
sMCRefMem.pSrcV = pSrcPic->pData[2];
sMCRefMem.iDstLineLuma = pDstPic->iLinesize[0];
sMCRefMem.iDstLineChroma = pDstPic->iLinesize[1];
sMCRefMem.iPicWidth = pDstPic->iWidthInPixel;
sMCRefMem.iPicHeight = pDstPic->iHeightInPixel;
}
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
iMbXyIndex = iMbY * iMbWidth + iMbX;
if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
iMbEcedNum++;
if (pSrcPic != NULL) {
DoMbECMvCopy (pCtx, pDstPic, pSrcPic, iMbXyIndex, iMbX, iMbY, &sMCRefMem);
} else { //pSrcPic == NULL
//Y component
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
for (int32_t i = 0; i < 16; ++i) {
memset (pDstData, 128, 16);
pDstData += iDstStride;
}
//U component
pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
for (int32_t i = 0; i < 8; ++i) {
memset (pDstData, 128, 8);
pDstData += iDstStride / 2;
}
//V component
pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
for (int32_t i = 0; i < 8; ++i) {
memset (pDstData, 128, 8);
pDstData += iDstStride / 2;
}
} //
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
} //iMbX
} //iMbY
pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+ ((iMbEcedNum * 100) / iMbNum) ;
}
//Mark erroneous frame as Ref Pic into DPB
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) {
@@ -183,10 +452,17 @@ void ImplementErrorCon (PWelsDecoderContext pCtx) {
if (ERROR_CON_DISABLE == pCtx->eErrorConMethod) {
pCtx->iErrorCode |= dsBitstreamError;
return;
} else if (ERROR_CON_FRAME_COPY == pCtx->eErrorConMethod) {
} else if ((ERROR_CON_FRAME_COPY == pCtx->eErrorConMethod)
|| (ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)) {
DoErrorConFrameCopy (pCtx);
} else if (ERROR_CON_SLICE_COPY == pCtx->eErrorConMethod) {
} else if ((ERROR_CON_SLICE_COPY == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)) {
DoErrorConSliceCopy (pCtx);
} else if ((ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)) {
GetAvilInfoFromCorrectMb (pCtx);
DoErrorConSliceMVCopy (pCtx);
} //TODO add other EC methods here in the future
pCtx->iErrorCode |= dsDataErrorConcealed;
pCtx->pDec->bIsComplete = false; // Set complete flag to false after do EC.

View File

@@ -40,6 +40,7 @@
*****************************************************************************/
#include "manage_dec_ref.h"
#include "error_concealment.h"
#include "error_code.h"
namespace WelsDec {
@@ -67,7 +68,7 @@ static void SetUnRef (PPicture pRef) {
pRef->bUsedAsRef = false;
pRef->bIsLongRef = false;
pRef->iFrameNum = -1;
pRef->iFramePoc = 0;
//pRef->iFramePoc = 0;
pRef->iLongTermFrameIdx = -1;
pRef->uiQualityId = -1;
pRef->uiTemporalId = -1;
@@ -119,9 +120,24 @@ int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
// IDR lost, set new
pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
pCtx->iErrorCode |= dsDataErrorConcealed;
memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod))
&& (NULL != pCtx->pPreviousDecodedPictureInDpb);
bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
&& (pRef->iHeightInPixel == pCtx->pPreviousDecodedPictureInDpb->iHeightInPixel);
if (bCopyPrevious) {
memcpy (pRef->pData[0], pCtx->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel);
memcpy (pRef->pData[1], pCtx->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
memcpy (pRef->pData[2], pCtx->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
} else {
memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
}
pRef->iFrameNum = 0;
pRef->iFramePoc = 0;
pRef->uiTemporalId = pRef->uiQualityId = 0;
@@ -244,6 +260,8 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
pCtx->pDec->iSpsId = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSpsId;
pCtx->pDec->iPpsId = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iPpsId;
for (j = pCurAU->uiStartPos; j <= pCurAU->uiEndPos; j++) {
if (pCurAU->pNalUnitsList[j]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR

View File

@@ -0,0 +1,909 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* cabac_decoder.cpp: cabac parse for syntax elements
*/
#include "parse_mb_syn_cabac.h"
#include "mv_pred.h"
#include "error_code.h"
namespace WelsDec {
#define IDX_UNUSED -1
static const int16_t g_kMaxPos [] = {IDX_UNUSED, 15, 14, 15, 3, 14, 3, 3, 14, 14};
static const int16_t g_kMaxC2 [] = {IDX_UNUSED, 4, 4, 4, 3, 4, 3, 3, 4, 4};
static const int16_t g_kBlockCat2CtxOffsetCBF[] = {IDX_UNUSED, 0, 4, 8, 12, 16, 12, 12, 16, 16};
static const int16_t g_kBlockCat2CtxOffsetMap [] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
static const int16_t g_kBlockCat2CtxOffsetLast[] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
static const int16_t g_kBlockCat2CtxOffsetOne [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
static const int16_t g_kBlockCat2CtxOffsetAbs [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
const uint8_t g_kTopBlkInsideMb[24] = { //for index with z-order 0~23
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 0, 1, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
0, 0, 1, 1, //--------------- --------- 4 5 6 7
1, 1, 1, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
0, 0, 1, 1, //---------------- chroma 8*8 block 16 17 18 19
0, 0, 1, 1 // 16 17 | 20 21 0 1 20 21 22 23
// 18 19 | 22 23
};
const uint8_t g_kLeftBlkInsideMb[24] = { //for index with z-order 0~23
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 1, 0, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
1, 1, 1, 1, //--------------- --------- 4 5 6 7
0, 1, 0, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
0, 1, 0, 1, //---------------- chroma 8*8 block 16 17 18 19
0, 1, 0, 1 // 16 17 | 20 21 0 1 20 21 22 23
// 18 19 | 22 23
};
void UpdateP16x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int32_t iRef32Bit = (int32_t) iRef;
const int32_t iRef4Bytes = (iRef32Bit << 24) | (iRef32Bit << 16) | (iRef32Bit << 8) | iRef32Bit;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef4Bytes);
ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef4Bytes);
//cache
ST32 (&pRefIndex[iListIdx][iCacheIdx ], iRef4Bytes);
ST32 (&pRefIndex[iListIdx][iCacheIdx6], iRef4Bytes);
}
void UpdateP8x16RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int16_t iRef16Bit = (int16_t) iRef;
const int16_t iRef2Bytes = (iRef16Bit << 8) | iRef16Bit;
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 8) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef2Bytes);
ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef2Bytes);
//cache
ST16 (&pRefIndex[iListIdx][iCacheIdx ], iRef2Bytes);
ST16 (&pRefIndex[iListIdx][iCacheIdx6], iRef2Bytes);
}
}
void UpdateP8x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 1] =
pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 4] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 5] = iRef;
}
void UpdateP16x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvd[2], const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 16; i += 2) {
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][i], LD64 (pMvd32));
}
}
void UpdateP16x8MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 4) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
//cache
ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
}
}
void UpdateP8x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 8) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
//cache
ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
}
}
int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal) {
uiBinVal = 0;
WELS_READ_VERIFY (DecodeTerminateCabac (pCtx->pCabacDecEngine, uiBinVal));
return ERR_NONE;
}
int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip) {
uiSkip = 0;
int32_t iCtxInc = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_SKIP) + (pNeighAvail->iTopAvail
&& pNeighAvail->iTopType != MB_TYPE_SKIP);
PWelsCabacCtx pBinCtx = (pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP + iCtxInc);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx, uiSkip));
return ERR_NONE;
}
int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal) {
uint32_t uiCode;
int32_t iIdxA = 0, iIdxB = 0;
int32_t iCtxInc;
uiBinVal = 0;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MB_TYPE_I; //I mode in I slice
iIdxA = (pNeighAvail->iLeftAvail) && (pNeighAvail->iLeftType != MB_TYPE_INTRA4x4
&& pNeighAvail->iLeftType != MB_TYPE_INTRA8x8);
iIdxB = (pNeighAvail->iTopAvail) && (pNeighAvail->iTopType != MB_TYPE_INTRA4x4
&& pNeighAvail->iTopType != MB_TYPE_INTRA8x8);
iCtxInc = iIdxA + iIdxB;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
uiBinVal = uiCode;
if (uiBinVal != 0) { //I16x16
WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
if (uiCode == 1)
uiBinVal = 25; //I_PCM
else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
uiBinVal = 1 + uiCode * 12;
//decoding of uiCbp:0,1,2
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
if (uiCode != 0) {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
uiBinVal += 4;
if (uiCode != 0)
uiBinVal += 4;
}
//decoding of I pred-mode: 0,1,2,3
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
uiBinVal += (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
uiBinVal += uiCode;
}
}
//I4x4
return ERR_NONE;
}
int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
uint32_t uiCode;
uiMbType = 0;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
if (uiCode) {
// Intra MB
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
if (uiCode) { // Intra 16x16
WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
if (uiCode) {
uiMbType = 30;
return ERR_NONE;//MB_TYPE_INTRA_PCM;
}
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
uiMbType = 6 + uiCode * 12;
//uiCbp: 0,1,2
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
if (uiCode) {
uiMbType += 4;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
if (uiCode)
uiMbType += 4;
}
//IPredMode: 0,1,2,3
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
uiMbType += (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
uiMbType += uiCode;
} else
// Intra 4x4
uiMbType = 5;
} else { // P MB
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
if (uiCode) { //second bit
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
if (uiCode)
uiMbType = 1;
else
uiMbType = 2;
} else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
if (uiCode)
uiMbType = 3;
else
uiMbType = 0;
}
}
return ERR_NONE;
}
int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
uint32_t uiCode;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SUBMB_TYPE;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
if (uiCode)
uiSubMbType = 0;
else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
uiSubMbType = 3 - uiCode;
} else {
uiSubMbType = 1;
}
}
return ERR_NONE;
}
int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal) {
uint32_t uiCode;
iBinVal = 0;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR, uiCode));
if (uiCode == 1)
iBinVal = -1;
else {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= uiCode;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= (uiCode << 2);
}
return ERR_NONE;
}
int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal) {
uint32_t uiCode;
int32_t iIdxA, iIdxB, iCtxInc;
int8_t* pChromaPredMode = pCtx->pCurDqLayer->pChromaPredMode;
int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
int32_t iLeftAvail = uiNeighAvail & 0x04;
int32_t iTopAvail = uiNeighAvail & 0x01;
int32_t iMbXy = pCtx->pCurDqLayer->iMbXyIndex;
int32_t iMbXyTop = iMbXy - pCtx->pCurDqLayer->iMbWidth;
int32_t iMbXyLeft = iMbXy - 1;
iBinVal = 0;
iIdxB = iTopAvail && (pChromaPredMode[iMbXyTop] > 0 && pChromaPredMode[iMbXyTop] <= 3)
&& pMbType[iMbXyTop] != MB_TYPE_INTRA_PCM;
iIdxA = iLeftAvail && (pChromaPredMode[iMbXyLeft] > 0 && pChromaPredMode[iMbXyLeft] <= 3)
&& pMbType[iMbXyLeft] != MB_TYPE_INTRA_PCM;
iCtxInc = iIdxA + iIdxB;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + iCtxInc, uiCode));
iBinVal = uiCode;
if (iBinVal != 0) {
uint32_t iSym;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, iSym));
if (iSym == 0) {
iBinVal = (iSym + 1);
return ERR_NONE;
}
iSym = 0;
do {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, uiCode));
++iSym;
} while ((uiCode != 0) && (iSym < 1));
if ((uiCode != 0) && (iSym == 1))
++ iSym;
iBinVal = (iSym + 1);
return ERR_NONE;
}
return ERR_NONE;
}
int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]) {
PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
int32_t pRefCount[2];
int32_t i, j;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int16_t pMv[4] = {0};
int16_t pMvd[4] = {0};
int8_t iRef[2] = {0};
int32_t iPartIdx;
int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
pRefCount[0] = pSliceHeader->uiRefCount[0];
pRefCount[1] = pSliceHeader->uiRefCount[1];
switch (pCurDqLayer->pMbType[iMbXy]) {
case MB_TYPE_16x16: {
iPartIdx = 0;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[0]));
if ((iRef[0] < 0) || (iRef[0] >= pRefCount[0]) || (ppRefPic[iRef[0]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[0] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
PredMv (pMotionVector, pRefIndex, 0, 4, iRef[0], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP16x16MotionInfo (pCurDqLayer, iRef[0], pMv);
UpdateP16x16MvdCabac (pCurDqLayer, pMvd, LIST_0);
}
break;
case MB_TYPE_16x8:
for (i = 0; i < 2; i++) {
iPartIdx = i << 3;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[i]));
if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
}
for (i = 0; i < 2; i++) {
iPartIdx = i << 3;
PredInter16x8Mv (pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
}
break;
case MB_TYPE_8x16:
for (i = 0; i < 2; i++) {
iPartIdx = i << 2;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[i]));
if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
}
for (i = 0; i < 2; i++) {
iPartIdx = i << 2;
PredInter8x16Mv (pMotionVector, pRefIndex, i << 2, iRef[i], pMv/*&mv[0], &mv[1]*/);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
}
break;
case MB_TYPE_8x8:
case MB_TYPE_8x8_REF0: {
int8_t pRefIdx[4] = {0}, pSubPartCount[4], pPartW[4];
uint32_t uiSubMbType;
//sub_mb_type, partition
for (i = 0; i < 4; i++) {
WELS_READ_VERIFY (ParseSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
if (uiSubMbType >= 4) { //invalid sub_mb_type
return ERR_INFO_INVALID_SUB_MB_TYPE;
}
pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterSubMbTypeInfo[uiSubMbType].iType;
pSubPartCount[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartCount;
pPartW[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartWidth;
}
for (i = 0; i < 4; i++) {
int16_t iIdx8 = i << 2;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iIdx8, pRefCount[0], 1,
pRefIdx[i]));
if ((pRefIdx[i] < 0) || (pRefIdx[i] >= pRefCount[0]) || (ppRefPic[pRefIdx[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
pRefIdx[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
}
//mv
for (i = 0; i < 4; i++) {
int8_t iPartCount = pSubPartCount[i];
uiSubMbType = pCurDqLayer->pSubMbType[iMbXy][i];
int16_t iPartIdx, iBlockW = pPartW[i];
uint8_t iScan4Idx, iCacheIdx;
iCacheIdx = g_kuiCache30ScanIdx[i << 2];
pRefIndex[0][iCacheIdx ] = pRefIndex[0][iCacheIdx + 1]
= pRefIndex[0][iCacheIdx + 6] = pRefIndex[0][iCacheIdx + 7] = pRefIdx[i];
for (j = 0; j < iPartCount; j++) {
iPartIdx = (i << 2) + j * iBlockW;
iScan4Idx = g_kuiScan4[iPartIdx];
iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
PredMv (pMotionVector, pRefIndex, iPartIdx, iBlockW, pRefIdx[i], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
if (SUB_MB_TYPE_8x8 == uiSubMbType) {
ST32 ((pMv + 2), LD32 (pMv));
ST32 ((pMvd + 2), LD32 (pMvd));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx], LD64 (pMv));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD64 (pMv));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx], LD64 (pMvd));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD64 (pMvd));
ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
ST64 (pMotionVector[0][iCacheIdx + 6], LD64 (pMv));
ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
ST64 (pMvdCache[0][iCacheIdx + 6], LD64 (pMvd));
} else if (SUB_MB_TYPE_8x4 == uiSubMbType) {
ST32 ((pMv + 2), LD32 (pMv));
ST32 ((pMvd + 2), LD32 (pMvd));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD64 (pMv));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD64 (pMvd));
ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
} else if (SUB_MB_TYPE_4x8 == uiSubMbType) {
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD32 (pMv));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD32 (pMvd));
ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
ST32 (pMotionVector[0][iCacheIdx + 6], LD32 (pMv));
ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
ST32 (pMvdCache[0][iCacheIdx + 6], LD32 (pMvd));
} else { //SUB_MB_TYPE_4x4
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
}
}
}
}
break;
default:
break;
}
return ERR_NONE;
}
int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
int8_t ref_idx[LIST_A][30],
int32_t iListIdx, int32_t iZOrderIdx, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal) {
if (iActiveRefNum == 1) {
iRefIdxVal = 0;
return ERR_NONE;
}
uint32_t uiCode;
int32_t iIdxA = 0, iIdxB = 0;
int32_t iCtxInc;
int8_t* pRefIdxInMB = pCtx->pCurDqLayer->pRefIndex[LIST_0][pCtx->pCurDqLayer->iMbXyIndex];
if (iZOrderIdx == 0) {
iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
} else if (iZOrderIdx == 4) {
iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
} else if (iZOrderIdx == 8) {
iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
} else {
iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
}
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + iCtxInc, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + 4, 1, uiCode));
++uiCode;
}
iRefIdxVal = (int8_t) uiCode;
return ERR_NONE;
}
int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal) {
uint32_t uiCode;
int32_t iIdxA = 0;
//int32_t sym;
int32_t iCtxInc;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MVD + iMvComp * CTX_NUM_MVD;
iMvdVal = 0;
if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 6] >= 0)
iIdxA = WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 6][iMvComp]);
if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 1] >= 0)
iIdxA += WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 1][iMvComp]);
if (iIdxA < 3)
iCtxInc = 0;
else if (iIdxA > 32)
iCtxInc = 2;
else
iCtxInc = 1;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeUEGMvCabac (pCtx->pCabacDecEngine, pBinCtx + 3, 3, uiCode));
iMvdVal = (int16_t) (uiCode + 1);
WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
if (uiCode) {
iMvdVal = -iMvdVal;
}
} else {
iMvdVal = 0;
}
return ERR_NONE;
}
int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiCbp) {
int32_t iIdxA = 0, iIdxB = 0, pALeftMb[2], pBTopMb[2];
uiCbp = 0;
uint32_t pCbpBit[6];
int32_t iCtxInc;
//Luma: bit by bit for 4 8x8 blocks in z-order
pBTopMb[0] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iTopCbp & (1 << 2)) == 0);
pBTopMb[1] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iTopCbp & (1 << 3)) == 0);
pALeftMb[0] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iLeftCbp & (1 << 1)) == 0);
pALeftMb[1] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iLeftCbp & (1 << 3)) == 0);
//left_top 8x8 block
iCtxInc = pALeftMb[0] + (pBTopMb[0] << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[0]));
if (pCbpBit[0])
uiCbp += 0x01;
//right_top 8x8 block
iIdxA = !pCbpBit[0];
iCtxInc = iIdxA + (pBTopMb[1] << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[1]));
if (pCbpBit[1])
uiCbp += 0x02;
//left_bottom 8x8 block
iIdxB = !pCbpBit[0];
iCtxInc = pALeftMb[1] + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[2]));
if (pCbpBit[2])
uiCbp += 0x04;
//right_bottom 8x8 block
iIdxB = !pCbpBit[1];
iIdxA = !pCbpBit[2];
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[3]));
if (pCbpBit[3])
uiCbp += 0x08;
//Chroma: bit by bit
iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4));
iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4));
//BitIdx = 0
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + CTX_NUM_CBP + iCtxInc,
pCbpBit[4]));
//BitIdx = 1
if (pCbpBit[4]) {
iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4) == 2);
iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4) == 2);
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + 2 * CTX_NUM_CBP + iCtxInc,
pCbpBit[5]));
uiCbp += 1 << (4 + pCbpBit[5]);
}
return ERR_NONE;
}
int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta) {
uint32_t uiCode;
PSlice pCurrSlice = & (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer);
iQpDelta = 0;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_DELTA_QP;
int32_t iCtxInc = (pCurrSlice->iLastDeltaQp != 0);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
if (uiCode != 0) {
WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pBinCtx + 2, 1, uiCode));
uiCode++;
iQpDelta = (uiCode + 1) >> 1;
if ((uiCode & 1) == 0)
iQpDelta = - iQpDelta;
}
pCurrSlice->iLastDeltaQp = iQpDelta;
return ERR_NONE;
}
int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t iZIndex, int32_t iResProperty,
PWelsDecoderContext pCtx, uint32_t& uiCbfBit) {
int8_t nA, nB/*, zigzag_idx = 0*/;
int32_t iCurrBlkXy = pCtx->pCurDqLayer->iMbXyIndex;
int32_t iTopBlkXy = iCurrBlkXy - pCtx->pCurDqLayer->iMbWidth; //default value: MB neighboring
int32_t iLeftBlkXy = iCurrBlkXy - 1; //default value: MB neighboring
uint8_t* pCbfDc = pCtx->pCurDqLayer->pCbfDc;
int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
int32_t iCtxInc;
uiCbfBit = 0;
nA = nB = IS_INTRA (pMbType[iCurrBlkXy]);
if (iResProperty == I16_LUMA_DC || iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) { //DC
if (pNeighAvail->iTopAvail)
nB = (pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iTopBlkXy] >> iResProperty) & 1);
if (pNeighAvail->iLeftAvail)
nA = (pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iLeftBlkXy] >> iResProperty) & 1);
iCtxInc = nA + (nB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
if (uiCbfBit)
pCbfDc[iCurrBlkXy] |= (1 << iResProperty);
} else { //AC
//for 4x4 blk, make sure blk-idx is correct
if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] != 0xff) { //top blk available
if (g_kTopBlkInsideMb[iZIndex])
iTopBlkXy = iCurrBlkXy;
nB = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] || pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM;
}
if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] != 0xff) { //left blk available
if (g_kLeftBlkInsideMb[iZIndex])
iLeftBlkXy = iCurrBlkXy;
nA = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] || pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM;
}
iCtxInc = nA + (nB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
}
return ERR_NONE;
}
int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
uint32_t& uiCoeffNum) {
uint32_t uiCode;
PWelsCabacCtx pMapCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MAP + g_kBlockCat2CtxOffsetMap [iResProperty];
PWelsCabacCtx pLastCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_LAST + g_kBlockCat2CtxOffsetLast[iResProperty];
int32_t i;
uiCoeffNum = 0;
int32_t i0 = 0;
int32_t i1 = g_kMaxPos[iResProperty];
for (i = i0; i < i1; ++i) {
//read significant
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pMapCtx + i, uiCode));
if (uiCode) {
* (pSignificantMap++) = 1;
++ uiCoeffNum;
//read last significant
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pLastCtx + i, uiCode));
if (uiCode) {
memset (pSignificantMap, 0, (i1 - i) * sizeof (int32_t));
return ERR_NONE;
}
} else
* (pSignificantMap++) = 0;
}
//deal with last pSignificantMap if no data
//if(i < i1+1)
{
*pSignificantMap = 1;
++uiCoeffNum;
}
return ERR_NONE;
}
int32_t ParseSignificantCoeffCabac (int32_t* pSignificant, int32_t iResProperty, PWelsDecoderContext pCtx) {
uint32_t uiCode;
PWelsCabacCtx pOneCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ONE + g_kBlockCat2CtxOffsetOne[iResProperty];
PWelsCabacCtx pAbsCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ABS + g_kBlockCat2CtxOffsetAbs[iResProperty];
const int16_t iMaxType = g_kMaxC2[iResProperty];
int32_t i = g_kMaxPos[iResProperty];
int32_t* pCoff = pSignificant + i;
int32_t c1 = 1;
int32_t c2 = 0;
for (; i >= 0; --i) {
if (*pCoff != 0) {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pOneCtx + c1, uiCode));
*pCoff += uiCode;
if (*pCoff == 2) {
WELS_READ_VERIFY (DecodeUEGLevelCabac (pCtx->pCabacDecEngine, pAbsCtx + c2, uiCode));
*pCoff += uiCode;
++c2;
c2 = WELS_MIN (c2, iMaxType);
c1 = 0;
} else if (c1) {
++c1;
c1 = WELS_MIN (c1, 4);
}
WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
if (uiCode)
*pCoff = - *pCoff;
}
pCoff--;
}
return ERR_NONE;
}
int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
int32_t iIndex, int32_t iMaxNumCoeff,
const uint8_t* pScanTable, int32_t iResProperty, short* sTCoeff, /*int mb_mode*/ uint8_t uiQp,
PWelsDecoderContext pCtx) {
int32_t iCurNzCacheIdx;
const uint16_t* pDeQuantMul = g_kuiDequantCoeff[uiQp];
uint32_t uiTotalCoeffNum = 0;
uint32_t uiCbpBit;
int32_t pSignificantMap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
WELS_READ_VERIFY (ParseCbfInfoCabac (pNeighAvail, pNonZeroCountCache, iIndex, iResProperty, pCtx, uiCbpBit));
if (uiCbpBit) { //has coeff
WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
}
iCurNzCacheIdx = g_kCacheNzcScanIdx[iIndex];
pNonZeroCountCache[iCurNzCacheIdx] = (uint8_t)uiTotalCoeffNum;
if (uiTotalCoeffNum == 0) {
return ERR_NONE;
}
int32_t j = 0;
if (iResProperty == I16_LUMA_DC) {
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j];
++j;
} while (j < 16);
} else if (iResProperty == CHROMA_DC_U) {
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[0];
++j;
} while (j < 16);
} else { //luma ac, chroma ac
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
++j;
} while (j < 16);
}
return ERR_NONE;
}
int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx) {
int32_t i;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
SBitStringAux* pBsAux = pCtx->pCurDqLayer->pBitStringAux;
SDqLayer* pCurLayer = pCtx->pCurDqLayer;
int32_t iDstStrideLuma = pCurLayer->pDec->iLinesize[0];
int32_t iDstStrideChroma = pCurLayer->pDec->iLinesize[1];
int32_t iMbX = pCurLayer->iMbX;
int32_t iMbY = pCurLayer->iMbY;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t iMbOffsetLuma = (iMbX + iMbY * iDstStrideLuma) << 4;
int32_t iMbOffsetChroma = (iMbX + iMbY * iDstStrideChroma) << 3;
uint8_t* pMbDstY = pCtx->pDec->pData[0] + iMbOffsetLuma;
uint8_t* pMbDstU = pCtx->pDec->pData[1] + iMbOffsetChroma;
uint8_t* pMbDstV = pCtx->pDec->pData[2] + iMbOffsetChroma;
uint8_t* pPtrSrc;
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA_PCM;
RestoreCabacDecEngineToBS (pCabacDecEngine, pBsAux);
intX_t iBytesLeft = pBsAux->pEndBuf - pBsAux->pCurBuf;
if (iBytesLeft < 384) {
return ERR_CABAC_NO_BS_TO_READ;
}
pPtrSrc = pBsAux->pCurBuf;
for (i = 0; i < 16; i++) { //luma
memcpy (pMbDstY , pPtrSrc, 16);
pMbDstY += iDstStrideLuma;
pPtrSrc += 16;
}
for (i = 0; i < 8; i++) { //cb
memcpy (pMbDstU, pPtrSrc, 8);
pMbDstU += iDstStrideChroma;
pPtrSrc += 8;
}
for (i = 0; i < 8; i++) { //cr
memcpy (pMbDstV, pPtrSrc, 8);
pMbDstV += iDstStrideChroma;
pPtrSrc += 8;
}
pBsAux->pCurBuf += 384;
pCurLayer->pLumaQp[iMbXy] = 0;
pCurLayer->pChromaQp[iMbXy] = 0;
memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
//step 4: cabac engine init
WELS_READ_VERIFY (InitReadBits (pBsAux, 1));
WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCabacDecEngine, pBsAux));
return ERR_NONE;
}
}

View File

@@ -45,7 +45,7 @@
namespace WelsDec {
#define MAX_LEVEL_PREFIX 15
void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer) {
int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc;
int32_t iCurXy, iTopXy = 0, iLeftXy = 0, iLeftTopXy = 0, iRightTopXy = 0;
int32_t iCurX, iCurY;
@@ -58,15 +58,18 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
iLeftXy = iCurXy - 1;
iLeftSliceIdc = pCurLayer->pSliceIdc[iLeftXy];
pNeighAvail->iLeftAvail = (iLeftSliceIdc == iCurSliceIdc);
pNeighAvail->iLeftCbp = pNeighAvail->iLeftAvail ? pCurLayer->pCbp[iLeftXy] : 0;
} else {
pNeighAvail->iLeftAvail = 0;
pNeighAvail->iLeftTopAvail = 0;
pNeighAvail->iLeftCbp = 0;
}
if (iCurY != 0) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
iTopSliceIdc = pCurLayer->pSliceIdc[iTopXy];
pNeighAvail->iTopAvail = (iTopSliceIdc == iCurSliceIdc);
pNeighAvail->iTopCbp = pNeighAvail->iTopAvail ? pCurLayer->pCbp[iTopXy] : 0;
if (iCurX != 0) {
iLeftTopXy = iTopXy - 1;
iLeftTopSliceIdc = pCurLayer->pSliceIdc[iLeftTopXy];
@@ -85,6 +88,7 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
pNeighAvail->iTopAvail = 0;
pNeighAvail->iLeftTopAvail = 0;
pNeighAvail->iRightTopAvail = 0;
pNeighAvail->iTopCbp = 0;
}
pNeighAvail->iLeftType = (pNeighAvail->iLeftAvail ? pCurLayer->pMbType[iLeftXy] : 0);
@@ -92,14 +96,11 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
pNeighAvail->iLeftTopType = (pNeighAvail->iLeftTopAvail ? pCurLayer->pMbType[iLeftTopXy] : 0);
pNeighAvail->iRightTopType = (pNeighAvail->iRightTopAvail ? pCurLayer->pMbType[iRightTopXy] : 0);
}
void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
PDqLayer pCurLayer) { //no matter slice type, intra_pred_constrained_flag
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
GetNeighborAvailMbType (pNeighAvail, pCurLayer);
if (pNeighAvail->iTopAvail) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
}
@@ -143,7 +144,7 @@ void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
pNonZeroCount[5 + 8 * 5] = -1;//unavailable
}
}
void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer) { //no matter slice type
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
@@ -189,7 +190,7 @@ void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZero
}
}
void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer) { //no matter slice type
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
@@ -235,8 +236,142 @@ void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZero
}
}
void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer) {
void WelsFillCacheInterCabac(PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
{
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
int32_t iLeftTopXy = 0;
int32_t iRightTopXy = 0;
//stuff non_zero_coeff_count from pNeighAvail(left and top)
WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
if (pNeighAvail->iTopAvail) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
}
if (pNeighAvail->iLeftAvail) {
iLeftXy = iCurXy - 1;
}
if (pNeighAvail->iLeftTopAvail) {
iLeftTopXy = iCurXy - 1 - pCurLayer->iMbWidth;
}
if (pNeighAvail->iRightTopAvail) {
iRightTopXy = iCurXy + 1 - pCurLayer->iMbWidth;
}
//stuff mv_cache and iRefIdxArray from left and top (inter)
if (pNeighAvail->iLeftAvail && IS_INTER (pNeighAvail->iLeftType)) {
ST32 (iMvArray[0][ 6], LD32 (pCurLayer->pMv[0][iLeftXy][ 3]));
ST32 (iMvArray[0][12], LD32 (pCurLayer->pMv[0][iLeftXy][ 7]));
ST32 (iMvArray[0][18], LD32 (pCurLayer->pMv[0][iLeftXy][11]));
ST32 (iMvArray[0][24], LD32 (pCurLayer->pMv[0][iLeftXy][15]));
ST32(iMvdCache[0][ 6], LD32(pCurLayer->pMvd[0][iLeftXy][ 3]));
ST32(iMvdCache[0][12], LD32(pCurLayer->pMvd[0][iLeftXy][ 7]));
ST32(iMvdCache[0][18], LD32(pCurLayer->pMvd[0][iLeftXy][11]));
ST32(iMvdCache[0][24], LD32(pCurLayer->pMvd[0][iLeftXy][15]));
iRefIdxArray[0][ 6] = pCurLayer->pRefIndex[0][iLeftXy][ 3];
iRefIdxArray[0][12] = pCurLayer->pRefIndex[0][iLeftXy][ 7];
iRefIdxArray[0][18] = pCurLayer->pRefIndex[0][iLeftXy][11];
iRefIdxArray[0][24] = pCurLayer->pRefIndex[0][iLeftXy][15];
} else {
ST32 (iMvArray[0][ 6], 0);
ST32 (iMvArray[0][12], 0);
ST32 (iMvArray[0][18], 0);
ST32 (iMvArray[0][24], 0);
ST32(iMvdCache[0][ 6], 0);
ST32(iMvdCache[0][12], 0);
ST32(iMvdCache[0][18], 0);
ST32(iMvdCache[0][24], 0);
if (0 == pNeighAvail->iLeftAvail) { //not available
iRefIdxArray[0][ 6] =
iRefIdxArray[0][12] =
iRefIdxArray[0][18] =
iRefIdxArray[0][24] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][ 6] =
iRefIdxArray[0][12] =
iRefIdxArray[0][18] =
iRefIdxArray[0][24] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iLeftTopAvail && IS_INTER (pNeighAvail->iLeftTopType)) {
ST32 (iMvArray[0][0], LD32 (pCurLayer->pMv[0][iLeftTopXy][15]));
ST32(iMvdCache[0][0], LD32(pCurLayer->pMvd[0][iLeftTopXy][15]));
iRefIdxArray[0][0] = pCurLayer->pRefIndex[0][iLeftTopXy][15];
} else {
ST32 (iMvArray[0][0], 0);
ST32(iMvdCache[0][0], 0);
if (0 == pNeighAvail->iLeftTopAvail) { //not available
iRefIdxArray[0][0] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][0] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
ST64(iMvdCache[0][1], LD64(pCurLayer->pMvd[0][iTopXy][12]));
ST64(iMvdCache[0][3], LD64(pCurLayer->pMvd[0][iTopXy][14]));
ST32 (&iRefIdxArray[0][1], LD32 (&pCurLayer->pRefIndex[0][iTopXy][12]));
} else {
ST64 (iMvArray[0][1], 0);
ST64 (iMvArray[0][3], 0);
ST64(iMvdCache[0][1], 0);
ST64(iMvdCache[0][3], 0);
if (0 == pNeighAvail->iTopAvail) { //not available
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
iRefIdxArray[0][3] =
iRefIdxArray[0][4] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
iRefIdxArray[0][3] =
iRefIdxArray[0][4] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
ST32(iMvdCache[0][5], LD32(pCurLayer->pMvd[0][iRightTopXy][12]));
iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
} else {
ST32 (iMvArray[0][5], 0);
if (0 == pNeighAvail->iRightTopAvail) { //not available
iRefIdxArray[0][5] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][5] = REF_NOT_IN_LIST;
}
}
//right-top 4*4 block unavailable
ST32 (iMvArray[0][ 9], 0);
ST32 (iMvArray[0][21], 0);
ST32 (iMvArray[0][11], 0);
ST32 (iMvArray[0][17], 0);
ST32 (iMvArray[0][23], 0);
ST32(iMvdCache[0][ 9], 0);
ST32(iMvdCache[0][21], 0);
ST32(iMvdCache[0][11], 0);
ST32(iMvdCache[0][17], 0);
ST32(iMvdCache[0][23], 0);
iRefIdxArray[0][ 9] =
iRefIdxArray[0][21] =
iRefIdxArray[0][11] =
iRefIdxArray[0][17] =
iRefIdxArray[0][23] = REF_NOT_AVAIL;
}
void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
{
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
@@ -298,7 +433,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][0] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
@@ -306,7 +440,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
} else {
ST64 (iMvArray[0][1], 0);
ST64 (iMvArray[0][3], 0);
if (0 == pNeighAvail->iTopAvail) { //not available
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
@@ -319,7 +452,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][4] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
@@ -331,7 +463,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][5] = REF_NOT_IN_LIST;
}
}
//right-top 4*4 block unavailable
ST32 (iMvArray[0][ 9], 0);
ST32 (iMvArray[0][21], 0);
@@ -358,9 +489,6 @@ int32_t PredIntra4x4Mode (int8_t* pIntraPredMode, int32_t iIdx4) {
return iBestMode;
}
#define MAX_PRED_MODE_ID_I16x16 3
#define MAX_PRED_MODE_ID_CHROMA 3
#define MAX_PRED_MODE_ID_I4x4 8
#define CHECK_I16_MODE(a, b, c, d) \
((a == g_ksI16PredInfo[a].iPredMode) && \
(b >= g_ksI16PredInfo[a].iLeftAvail) && \
@@ -760,216 +888,6 @@ int32_t WelsResidualBlockCavlc (SVlcTable* pVlcTable, uint8_t* pNonZeroCountCach
return 0;
}
int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
if (pNeighAvail->iLeftAvail) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
iSampleAvail[18] =
iSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail) { //top_left
iSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail) { //top
iSampleAvail[1] =
iSampleAvail[2] =
iSampleAvail[3] =
iSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail) { //top_right
iSampleAvail[5] = 1;
}
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
const int32_t kiPrevIntra4x4PredMode = uiCode;
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (kiPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else { //kPrevIntra4x4PredMode == 0
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
const int32_t kiRemIntra4x4PredMode = uiCode;
if (kiRemIntra4x4PredMode < kiPredMode) {
iBestMode = kiRemIntra4x4PredMode;
} else {
iBestMode = kiRemIntra4x4PredMode + 1;
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
iSampleAvail[18] =
iSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) { //top_left
iSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) { //top
iSampleAvail[1] =
iSampleAvail[2] =
iSampleAvail[3] =
iSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) { //top_right
iSampleAvail[5] = 1;
}
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
const int32_t kiPrevIntra4x4PredMode = uiCode; //1bit
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (kiPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else { //kPrevIntra4x4PredMode == 0
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
const int32_t kiRemIntra4x4PredMode = uiCode;
if (kiRemIntra4x4PredMode < kiPredMode) {
iBestMode = kiRemIntra4x4PredMode;
} else {
iBestMode = kiRemIntra4x4PredMode + 1;
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
if (pNeighAvail->iLeftAvail) {
uiNeighAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail) {
uiNeighAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail) {
uiNeighAvail |= 1;
}
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
uiNeighAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
uiNeighAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
uiNeighAvail |= 1;
}
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseInterInfo (PWelsDecoderContext pCtx, int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30],
PBitStringAux pBs) {
PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;

View File

@@ -81,6 +81,7 @@ PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const
iLumaSize = iPicWidth * iPicHeight;
iChromaSize = iPicChromaWidth * iPicChromaHeight;
pPic->pBuffer[0] = static_cast<uint8_t*> (WelsMalloc (iLumaSize /* luma */
+ (iChromaSize << 1) /* Cb,Cr */, "_pic->buffer[0]"));
memset (pPic->pBuffer[0], 128, (iLumaSize + (iChromaSize << 1)));
@@ -94,8 +95,6 @@ PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const
pPic->pData[1] = pPic->pBuffer[1] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[1]) * PADDING_LENGTH) >> 1);
pPic->pData[2] = pPic->pBuffer[2] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[2]) * PADDING_LENGTH) >> 1);
pPic->iPlanes = 3; // yv12 in default
pPic->iWidthInPixel = kiPicWidth;
pPic->iHeightInPixel = kiPicHeight;

View File

@@ -164,24 +164,7 @@ int32_t RecI16x16Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLe
return ERR_NONE;
}
typedef struct TagMCRefMember {
uint8_t* pDstY;
uint8_t* pDstU;
uint8_t* pDstV;
uint8_t* pSrcY;
uint8_t* pSrcU;
uint8_t* pSrcV;
int32_t iSrcLineLuma;
int32_t iSrcLineChroma;
int32_t iDstLineLuma;
int32_t iDstLineChroma;
int32_t iPicWidth;
int32_t iPicHeight;
} sMCRefMember;
//according to current 8*8 block ref_index to gain reference picture
static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx, int8_t* pRefIdxList,
int32_t iIndex) {
@@ -202,32 +185,18 @@ static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx,
#ifndef MC_FLOW_SIMPLE_JUDGE
#define MC_FLOW_SIMPLE_JUDGE 1
#endif //MC_FLOW_SIMPLE_JUDGE
static inline void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
int32_t iExpandWidth = PADDING_LENGTH;
int32_t iExpandHeight = PADDING_LENGTH;
int16_t iMVX = iMVs[0] >> 2;
int16_t iMVY = iMVs[1] >> 2;
int32_t iMVOffsetLuma = iMVX + iMVY * pMCRefMem->iSrcLineLuma;
int32_t iMVOffsetChroma = (iMVX >> 1) + (iMVY >> 1) * pMCRefMem->iSrcLineChroma;
int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
int32_t iIntMVx = iFullMVx >> 2;//integer pixel
int32_t iIntMVy = iFullMVy >> 2;
iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) << 2), ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) << 2));
iFullMVy = WELS_CLIP3 (iFullMVy, ((-PADDING_LENGTH + 2) << 2), ((pMCRefMem->iPicHeight + PADDING_LENGTH - 19) << 2));
int32_t iSrcPixOffsetLuma = iXOffset + iYOffset * pMCRefMem->iSrcLineLuma;
int32_t iSrcPixOffsetChroma = (iXOffset >> 1) + (iYOffset >> 1) * pMCRefMem->iSrcLineChroma;
int32_t iSrcPixOffsetLuma = (iFullMVx >> 2) + (iFullMVy >> 2) * pMCRefMem->iSrcLineLuma;
int32_t iSrcPixOffsetChroma = (iFullMVx >> 3) + (iFullMVy >> 3) * pMCRefMem->iSrcLineChroma;
int32_t iBlkWidthChroma = iBlkWidth >> 1;
int32_t iBlkHeightChroma = iBlkHeight >> 1;
int32_t iPicWidthChroma = pMCRefMem->iPicWidth >> 1;
int32_t iPicHeightChroma = pMCRefMem->iPicHeight >> 1;
//the offset only for luma padding if MV violation as there was 5-tap (-2, -1, 0, 1, 2) filter for luma (horizon and vertical)
int32_t iPadOffset = 2 + (pMCRefMem->iSrcLineLuma << 1); //(-2, -2) pixel location as the starting point
uint8_t* pSrcY = pMCRefMem->pSrcY + iSrcPixOffsetLuma;
uint8_t* pSrcU = pMCRefMem->pSrcU + iSrcPixOffsetChroma;
@@ -235,58 +204,14 @@ static inline void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iY
uint8_t* pDstY = pMCRefMem->pDstY;
uint8_t* pDstU = pMCRefMem->pDstU;
uint8_t* pDstV = pMCRefMem->pDstV;
bool bExpand = false;
ENFORCE_STACK_ALIGN_1D (uint8_t, uiExpandBuf, (PADDING_LENGTH + 6) * (PADDING_LENGTH + 6), 16);
pMCFunc->pMcLumaFunc (pSrcY, pMCRefMem->iSrcLineLuma, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth,
iBlkHeight);
pMCFunc->pMcChromaFunc (pSrcU, pMCRefMem->iSrcLineChroma, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
iBlkWidthChroma, iBlkHeightChroma);
pMCFunc->pMcChromaFunc (pSrcV, pMCRefMem->iSrcLineChroma, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
iBlkWidthChroma, iBlkHeightChroma);
if (iFullMVx & 0x07) {
iExpandWidth -= 3;
}
if (iFullMVy & 0x07) {
iExpandHeight -= 3;
}
#ifdef MC_FLOW_SIMPLE_JUDGE
if (iIntMVx < -iExpandWidth ||
iIntMVy < -iExpandHeight ||
iIntMVx + iBlkWidth > pMCRefMem->iPicWidth - 1 + iExpandWidth ||
iIntMVy + iBlkHeight > pMCRefMem->iPicHeight - 1 + iExpandHeight)
#else
if (iIntMVx < -iExpandWidth ||
iIntMVy < -iExpandHeight ||
iIntMVx + PADDING_LENGTH > pMCRefMem->iPicWidth + iExpandWidth ||
iIntMVy + PADDING_LENGTH > pMCRefMem->iPicHeight + iExpandHeight)
#endif
{
FillBufForMc (uiExpandBuf, 21, pSrcY, pMCRefMem->iSrcLineLuma, iMVOffsetLuma - iPadOffset,
iBlkWidth + 5, iBlkHeight + 5, iIntMVx - 2, iIntMVy - 2, pMCRefMem->iPicWidth, pMCRefMem->iPicHeight);
pMCFunc->pMcLumaFunc (uiExpandBuf + 44, 21, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth,
iBlkHeight); //44=2+2*21
bExpand = true;
} else {
pSrcY += iMVOffsetLuma;
pMCFunc->pMcLumaFunc (pSrcY, pMCRefMem->iSrcLineLuma, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth,
iBlkHeight);
}
if (bExpand) {
FillBufForMc (uiExpandBuf, 21, pSrcU, pMCRefMem->iSrcLineChroma, iMVOffsetChroma, iBlkWidthChroma + 1,
iBlkHeightChroma + 1, iFullMVx >> 3, iFullMVy >> 3, iPicWidthChroma, iPicHeightChroma);
pMCFunc->pMcChromaFunc (uiExpandBuf, 21, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma,
iBlkHeightChroma);
FillBufForMc (uiExpandBuf, 21, pSrcV, pMCRefMem->iSrcLineChroma, iMVOffsetChroma, iBlkWidthChroma + 1,
iBlkHeightChroma + 1, iFullMVx >> 3, iFullMVy >> 3, iPicWidthChroma, iPicHeightChroma);
pMCFunc->pMcChromaFunc (uiExpandBuf, 21, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma,
iBlkHeightChroma);
} else {
pSrcU += iMVOffsetChroma;
pSrcV += iMVOffsetChroma;
pMCFunc->pMcChromaFunc (pSrcU, pMCRefMem->iSrcLineChroma, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
iBlkWidthChroma, iBlkHeightChroma);
pMCFunc->pMcChromaFunc (pSrcV, pMCRefMem->iSrcLineChroma, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
iBlkWidthChroma, iBlkHeightChroma);
}
}
void GetInterPred (uint8_t* pPredY, uint8_t* pPredCb, uint8_t* pPredCr, PWelsDecoderContext pCtx) {
@@ -464,88 +389,4 @@ int32_t RecChroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLeve
return ERR_NONE;
}
void FillBufForMc (uint8_t* pBuf, int32_t iBufStride, uint8_t* pSrc, int32_t iSrcStride, int32_t iSrcOffset,
int32_t iBlockWidth, int32_t iBlockHeight, int32_t iSrcX, int32_t iSrcY, int32_t iPicWidth, int32_t iPicHeight) {
int32_t iY;
int32_t iStartY, iStartX, iEndY, iEndX;
int32_t iOffsetAdj = 0;
int32_t iAddrSrc, iAddrBuf;
int32_t iNum, iNum1;
uint8_t* pBufSrc, *pBufDst;
uint8_t* pBufSrc1, *pBufDst1;
if (iSrcY >= iPicHeight) {
iOffsetAdj += (iPicHeight - 1 - iSrcY) * iSrcStride;
iSrcY = iPicHeight - 1;
} else if (iSrcY <= -iBlockHeight) {
iOffsetAdj += (1 - iBlockHeight - iSrcY) * iSrcStride;
iSrcY = 1 - iBlockHeight;
}
if (iSrcX >= iPicWidth) {
iOffsetAdj += (iPicWidth - 1 - iSrcX);
iSrcX = iPicWidth - 1;
} else if (iSrcX <= -iBlockWidth) {
iOffsetAdj += (1 - iBlockWidth - iSrcX);
iSrcX = 1 - iBlockWidth;
}
iOffsetAdj += iSrcOffset;
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) > (b) ? (b) : (a))
iStartY = MAX (0, -iSrcY);
iStartX = MAX (0, -iSrcX);
iEndY = MIN (iBlockHeight, iPicHeight - iSrcY);
iEndX = MIN (iBlockWidth, iPicWidth - iSrcX);
// copy existing part
iAddrSrc = iStartX + iStartY * iSrcStride;
iAddrBuf = iStartX + iStartY * iBufStride;
iNum = iEndX - iStartX;
for (iY = iStartY; iY < iEndY; iY++) {
memcpy (pBuf + iAddrBuf, pSrc + iOffsetAdj + iAddrSrc, iNum);
iAddrSrc += iSrcStride;
iAddrBuf += iBufStride;
}
//top
pBufSrc = pBuf + iStartX + iStartY * iBufStride;
pBufDst = pBuf + iStartX;
iNum = iEndX - iStartX;
for (iY = 0; iY < iStartY; iY++) {
memcpy (pBufDst, pBufSrc, iNum);
pBufDst += iBufStride;
}
//bottom
pBufSrc = pBuf + iStartX + (iEndY - 1) * iBufStride;
pBufDst = pBuf + iStartX + iEndY * iBufStride;
iNum = iEndX - iStartX;
for (iY = iEndY; iY < iBlockHeight; iY++) {
memcpy (pBufDst, pBufSrc, iNum);
pBufDst += iBufStride;
}
pBufSrc = pBuf + iStartX;
pBufDst = pBuf;
iNum = iStartX;
pBufSrc1 = pBuf + iEndX - 1;
pBufDst1 = pBuf + iEndX;
iNum1 = iBlockWidth - iEndX;
for (iY = 0; iY < iBlockHeight; iY++) {
//left
memset (pBufDst, pBufSrc[0], iNum);
pBufDst += iBufStride;
pBufSrc += iBufStride;
//right
memset (pBufDst1, pBufSrc1[0], iNum1);
pBufDst1 += iBufStride;
pBufSrc1 += iBufStride;
}
}
} // namespace WelsDec

View File

@@ -113,3 +113,30 @@ WELS_EXTERN IdctResAddPred_mmx
emms
ret
;void WelsBlockZero16x16_sse2(int16_t * block, int32_t stride);
WELS_EXTERN WelsBlockZero16x16_sse2
%assign push_num 0
LOAD_2_PARA
SIGN_EXTENSION r1, r1d
shl r1, 1
pxor xmm0, xmm0
%rep 16
movdqa [r0], xmm0
movdqa [r0+16], xmm0
add r0, r1
%endrep
ret
;void WelsBlockZero8x8_sse2(int16_t * block, int32_t stride);
WELS_EXTERN WelsBlockZero8x8_sse2
%assign push_num 0
LOAD_2_PARA
SIGN_EXTENSION r1, r1d
shl r1, 1
pxor xmm0, xmm0
%rep 8
movdqa [r0], xmm0
add r0, r1
%endrep
ret

View File

@@ -104,7 +104,7 @@ virtual long EXTAPI GetOption (DECODER_OPTION eOptID, void* pOption);
PWelsDecoderContext m_pDecContext;
welsCodecTrace* m_pWelsTrace;
int32_t InitDecoder (void);
int32_t InitDecoder (const bool);
void UninitDecoder (void);
#ifdef OUTPUT_BIT_STREAM

View File

@@ -53,6 +53,7 @@
#include "decoder_core.h"
#include "error_concealment.h"
#include "measure_time.h"
extern "C" {
#include "decoder_core.h"
#include "manage_dec_ref.h"
@@ -196,7 +197,7 @@ long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
}
// H.264 decoder initialization,including memory allocation,then open it ready to decode
iRet = InitDecoder();
iRet = InitDecoder (pParam->bParseOnly);
if (iRet)
return iRet;
@@ -231,16 +232,18 @@ void CWelsDecoder::UninitDecoder (void) {
}
// the return value of this function is not suitable, it need report failure info to upper layer.
int32_t CWelsDecoder::InitDecoder (void) {
int32_t CWelsDecoder::InitDecoder (const bool bParseOnly) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::init_decoder(), openh264 codec version = %s",
VERSION_NUMBER);
if (m_pDecContext) //free
UninitDecoder();
m_pDecContext = (PWelsDecoderContext)WelsMalloc (sizeof (SWelsDecoderContext), "m_pDecContext");
if (NULL == m_pDecContext)
return cmMallocMemeError;
return WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
return WelsInitDecoder (m_pDecContext, bParseOnly, &m_pWelsTrace->m_sLogCtx);
}
/*
@@ -274,7 +277,7 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
return cmInitParaError;
iVal = * ((int*)pOption); // int value for error concealment idc
iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_COPY);
iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal;
InitErrorCon (m_pDecContext);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
@@ -301,8 +304,13 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
m_pWelsTrace->SetTraceCallbackContext (ctx);
}
return cmResultSuccess;
} else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
"CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
return cmInitParaError;
}
return cmInitParaError;
}
@@ -358,6 +366,16 @@ long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
iVal = (int) m_pDecContext->eErrorConMethod;
* ((int*)pOption) = iVal;
return cmResultSuccess;
} else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
(m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
memset (&m_pDecContext->sDecoderStatistics, 0, sizeof (SDecoderStatistics));
m_pDecContext->dDecTime = 0;
return cmResultSuccess;
}
return cmInitParaError;
@@ -389,11 +407,14 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
m_pDecContext->bInstantDecFlag = true;
}
int64_t iStart, iEnd;
iStart = WelsTime();
ppDst[0] = ppDst[1] = ppDst[2] = NULL;
m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
memset (pDstInfo, 0, sizeof (SBufferInfo));
pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
#ifdef LONG_TERM_REF
m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
@@ -402,9 +423,14 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
#endif
m_pDecContext->iFeedbackTidInAu = -1; //initialize
if (pDstInfo) {
pDstInfo->uiOutYuvTimeStamp = 0;
m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
} else {
m_pDecContext->uiTimeStamp = 0;
}
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
pDstInfo); //iErrorCode has been modified in this function
pDstInfo, NULL); //iErrorCode has been modified in this function
m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
if (m_pDecContext->iErrorCode) {
EWelsNalUnitType eNalType =
@@ -421,7 +447,6 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
#else
m_pDecContext->bReferenceLostAtT0Flag = true;
#endif
ResetParameterSetsState (m_pDecContext); //initial SPS&PPS ready flag
}
}
@@ -439,18 +464,79 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
if ((m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
//TODO after dec status updated
m_pDecContext->iErrorCode |= dsDataErrorConcealed;
if (m_pDecContext->eErrorConMethod == ERROR_CON_FRAME_COPY)
m_pDecContext->sDecoderStatistics.uiAvgEcRatio = (m_pDecContext->sDecoderStatistics.uiAvgEcRatio *
m_pDecContext->sDecoderStatistics.uiEcFrameNum) + 100;
//
if ((m_pDecContext->sDecoderStatistics.uiWidth != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iWidth)
|| (m_pDecContext->sDecoderStatistics.uiHeight != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iHeight)) {
m_pDecContext->sDecoderStatistics.uiResolutionChangeTimes++;
m_pDecContext->sDecoderStatistics.uiWidth = pDstInfo->UsrData.sSystemBuffer.iWidth;
m_pDecContext->sDecoderStatistics.uiHeight = pDstInfo->UsrData.sSystemBuffer.iHeight;
}
m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
m_pDecContext->sDecoderStatistics.uiEcFrameNum++;
m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiAvgEcRatio /
m_pDecContext->sDecoderStatistics.uiEcFrameNum;
}
iEnd = WelsTime();
m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
return (DECODING_STATE) m_pDecContext->iErrorCode;
}
// else Error free, the current codec works well
if (pDstInfo->iBufferStatus == 1) {
if ((m_pDecContext->sDecoderStatistics.uiWidth != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iWidth)
|| (m_pDecContext->sDecoderStatistics.uiHeight != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iHeight)) {
m_pDecContext->sDecoderStatistics.uiResolutionChangeTimes++;
m_pDecContext->sDecoderStatistics.uiWidth = pDstInfo->UsrData.sSystemBuffer.iWidth;
m_pDecContext->sDecoderStatistics.uiHeight = pDstInfo->UsrData.sSystemBuffer.iHeight;
}
m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
}
iEnd = WelsTime();
m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
return dsErrorFree;
}
DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
const int kiSrcLen,
SParserBsInfo* pDstInfo) {
//TODO, add function here
if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
return dsOutOfMemory;
}
if (kiSrcLen > 0 && kpSrc != NULL) {
#ifdef OUTPUT_BITSTREAM
if (m_pFBS) {
WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
WelsFflush (m_pFBS);
}
#endif//OUTPUT_BIT_STREAM
m_pDecContext->bEndOfStreamFlag = false;
} else {
//For application MODE, the error detection should be added for safe.
//But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
m_pDecContext->bEndOfStreamFlag = true;
m_pDecContext->bInstantDecFlag = true;
}
m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
m_pDecContext->pParserBsInfo = pDstInfo;
pDstInfo->iNalNum = 0;
pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
if(pDstInfo) {
m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
pDstInfo->uiOutBsTimeStamp = 0;
} else {
m_pDecContext->uiTimeStamp = 0;
}
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
return (DECODING_STATE) m_pDecContext->iErrorCode;
}

View File

@@ -2,6 +2,7 @@ DECODER_SRCDIR=codec/decoder
DECODER_CPP_SRCS=\
$(DECODER_SRCDIR)/core/src/au_parser.cpp\
$(DECODER_SRCDIR)/core/src/bit_stream.cpp\
$(DECODER_SRCDIR)/core/src/cabac_decoder.cpp\
$(DECODER_SRCDIR)/core/src/deblocking.cpp\
$(DECODER_SRCDIR)/core/src/decode_mb_aux.cpp\
$(DECODER_SRCDIR)/core/src/decode_slice.cpp\
@@ -16,6 +17,7 @@ DECODER_CPP_SRCS=\
$(DECODER_SRCDIR)/core/src/mem_align.cpp\
$(DECODER_SRCDIR)/core/src/memmgr_nal_unit.cpp\
$(DECODER_SRCDIR)/core/src/mv_pred.cpp\
$(DECODER_SRCDIR)/core/src/parse_mb_syn_cabac.cpp\
$(DECODER_SRCDIR)/core/src/parse_mb_syn_cavlc.cpp\
$(DECODER_SRCDIR)/core/src/pic_queue.cpp\
$(DECODER_SRCDIR)/core/src/rec_mb.cpp\

View File

@@ -106,7 +106,8 @@ int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaS
*/
int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialLayerInternal* pLayerParamInternal,
const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
const uint32_t kiSpsId, const bool kbEnableFrameCropping, bool bEnableRc);
const uint32_t kiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
const int32_t kiDlayerCount);
/*!
* \brief initialize subset pSps based on configurable parameters in svc
@@ -138,7 +139,9 @@ int32_t WelsInitPps (SWelsPPS* pPps,
SSubsetSps* pSubsetSps,
const uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps);
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag);
int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
int32_t WelsAdjustLevel( SSpatialLayerConfig* pSpatialLayer);
}
#endif//WELS_ACCESS_UNIT_PARSER_H__

View File

@@ -70,7 +70,7 @@ int32_t AllocateBsOutputBuffer (CMemoryAlign* pMa, const int32_t iNeededLen, int
* \param pEncCtx sWelsEncCtx*
* \return successful - 0; otherwise none 0 for failed
*/
int32_t InitFunctionPointers (SWelsFuncPtrList* pFuncList, SWelsSvcCodingParam* _param, uint32_t uiCpuFlag);
int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* _param, uint32_t uiCpuFlag);
///*!
// * \brief decide frame type (IDR/P frame)

View File

@@ -221,11 +221,14 @@ typedef struct TagWelsEncCtx {
SEncoderStatistics sEncoderStatistics;
int32_t iStatisticsLogInterval;
int64_t iLastStatisticsLogTs;
int64_t iTotalEncodedBits;
int64_t iLastStatisticsBits;
int64_t iLastStatisticsFrameCount;
int32_t iEncoderError;
WELS_MUTEX mutexEncoderError;
bool bDeliveryFlag;
SStateCtx sWelsCabacContexts[4][WELS_QP_MAX + 1][WELS_CONTEXT_COUNT];
#ifdef ENABLE_FRAME_DUMP
bool bDependencyRecFlag[MAX_DEPENDENCY_LAYER];
bool bRecFlag;

View File

@@ -105,9 +105,10 @@ int32_t ForceCodingIDR (sWelsEncCtx* pCtx);
* \brief Wels SVC encoder parameters adjustment
* SVC adjustment results in new requirement in memory blocks adjustment
*/
int32_t WelsBitRateVerification(SLogContext* pLogCtx,SSpatialLayerConfig* pLayerParam,int32_t iLayerId);
int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNew);
void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam);
void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer);
int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer);
int32_t WelsEncoderApplyLTR (SLogContext* pLogCtx, sWelsEncCtx** ppCtx, SLTRConfig* pLTRValue);
int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest);

View File

@@ -118,9 +118,6 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
int8_t iDecompStages; // GOP size dependency
int32_t iMaxNumRefFrame;
//setting this according to link type in use MAY invoke some algorithms targeting higher coding efficiency
bool bIsLosslessLink;
public:
TagWelsSvcCodingParam() {
FillDefault();
@@ -139,7 +136,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
param.iComplexityMode = MEDIUM_COMPLEXITY;
param.iTargetBitrate = 0; // overall target bitrate introduced in RC module
param.iMaxBitrate = MAX_BIT_RATE;
param.iMaxBitrate = UNSPECIFIED_BIT_RATE;
param.iMultipleThreadIdc = 1;
param.iLTRRefNum = 0;
@@ -157,7 +154,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
/* Rate Control */
param.iRCMode = RC_QUALITY_MODE;
param.iPaddingFlag = 0;
param.iEntropyCodingModeFlag = 0;
param.bEnableDenoise = false; // denoise control
param.bEnableSceneChangeDetect = true; // scene change detection control
param.bEnableBackgroundDetection = true; // background detection control
@@ -173,7 +170,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
param.iMinQp = 0;
param.iUsageType = CAMERA_VIDEO_REAL_TIME;
param.uiMaxNalSize = 0;
param.bIsLosslessLink = false;
for (int32_t iLayer = 0; iLayer < MAX_SPATIAL_LAYER_NUM; iLayer++) {
param.sSpatialLayers[iLayer].uiProfileIdc = PRO_BASELINE;
param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_5_0;
@@ -182,7 +179,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
param.sSpatialLayers[iLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500;
param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;
param.sSpatialLayers[iLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
for (int32_t idx = 0; idx < kiLesserSliceNum; idx++)
param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960;
@@ -205,22 +202,6 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
iCountThreadsNum = 1; // # derived from disable_multiple_slice_idc (=0 or >1) means;
iDecompStages = 0; // GOP size dependency, unknown here and be revised later
iComplexityMode = MEDIUM_COMPLEXITY;
memset (sDependencyLayers, 0, sizeof (SSpatialLayerInternal)*MAX_DEPENDENCY_LAYER);
memset (sSpatialLayers, 0 , sizeof (SSpatialLayerConfig)*MAX_SPATIAL_LAYER_NUM);
//init multi-slice
sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500;
sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = 1;
const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
for (int32_t idx = 0; idx < kiLesserSliceNum; idx++)
sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960;
sSpatialLayers[0].iDLayerQp = SVC_QUALITY_BASE_QP;
bIsLosslessLink = false;
}
int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam) {
@@ -240,7 +221,8 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
int8_t iIdxSpatial = 0;
EProfileIdc uiProfileIdc = PRO_BASELINE;
if (iEntropyCodingModeFlag)
uiProfileIdc = PRO_MAIN;
SSpatialLayerInternal* pDlp = &sDependencyLayers[0];
while (iIdxSpatial < iSpatialLayerNum) {
@@ -298,7 +280,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
iLoopFilterDisableIdc = pCodingParam.iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries,
iLoopFilterAlphaC0Offset = pCodingParam.iLoopFilterAlphaC0Offset; // AlphaOffset: valid range [-6, 6], default 0
iLoopFilterBetaOffset = pCodingParam.iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0
iEntropyCodingModeFlag = pCodingParam.iEntropyCodingModeFlag;
bEnableFrameCroppingFlag = pCodingParam.bEnableFrameCroppingFlag;
/* Rate Control */
@@ -459,7 +441,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
const uint8_t* pTemporalIdList = &g_kuiTemporalIdListTable[iDecStages][0];
SSpatialLayerInternal* pDlp = &sDependencyLayers[0];
SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0];
EProfileIdc uiProfileIdc = PRO_BASELINE;
EProfileIdc uiProfileIdc = iEntropyCodingModeFlag ? PRO_MAIN : PRO_BASELINE;
int8_t i = 0;
while (i < iSpatialLayerNum) {
@@ -492,7 +474,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
return ENC_RETURN_INVALIDINPUT;
}
uiProfileIdc = PRO_SCALABLE_BASELINE;
uiProfileIdc = iEntropyCodingModeFlag ? PRO_SCALABLE_HIGH : PRO_SCALABLE_BASELINE;
++ pDlp;
++ pSpatialLayer;
++ i;

View File

@@ -147,7 +147,7 @@ uint8_t uiChromaQpIndexOffset;
// /* potential application for High profile */
// bool bPicOrderPresentFlag;
bool bEntropyCodingModeFlag;
bool bDeblockingFilterControlPresentFlag;
// bool bConstainedIntraPredFlag;

View File

@@ -159,7 +159,7 @@ int32_t iBitRate;
int32_t iPreviousBitrate;
int32_t iPreviousGopSize;
double fFrameRate;
int32_t iBitsPerFrame; // *INT_MULTIPLY
int64_t iBitsPerFrame; // *INT_MULTIPLY
double dPreviousFps;
// bits allocation and status

View File

@@ -0,0 +1,83 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* \file set_mb_syn_cabac.h
*
* \brief Seting all syntax elements of mb and encoding residual with cabac
*
* \date 09/27/2014 Created
*
*************************************************************************************
*/
#ifndef SET_MB_SYN_CABAC_H_
#define SET_MB_SYN_CABAC_H_
#include "typedefs.h"
#include "bit_stream.h"
#include "wels_common_defs.h"
namespace WelsEnc {
#define WELS_QP_MAX 51
typedef struct TagStateCtx {
uint8_t m_uiState;
uint8_t m_uiValMps;
} SStateCtx;
typedef struct TagCabacCtx {
uint32_t m_uiLow;
uint32_t m_uiRange;
SStateCtx m_sStateCtx[WELS_CONTEXT_COUNT];
uint8_t* m_pBufStart;
uint8_t* m_pBufEnd;
uint8_t* m_pBufCur;
uint8_t m_iBitsOutstanding;
uint32_t m_uData;
uint32_t m_uiBitsUsed;
uint32_t m_iFirstFlag;
uint32_t m_uiBinCountsInNalUnits;
} SCabacCtx;
void WelsCabacContextInit (void* pCtx, SCabacCtx* pCbCtx, int32_t iModel);
void WelsCabacEncodeInit (SCabacCtx* pCbCtx, uint8_t* pBuf, uint8_t* pEnd);
void WelsCabacEncodeDecision (SCabacCtx* pCbCtx, int32_t iCtx, uint32_t uiBin);
void WelsCabacEncodeBypassOne (SCabacCtx* pCbCtx, uint32_t uiBin);
void WelsCabacEncodeTerminate (SCabacCtx* pCbCtx, uint32_t uiBin);
void WelsCabacEncodeUeBypass (SCabacCtx* pCbCtx, int32_t iExpBits, uint32_t uiVal);
void WelsCabacEncodeFlush (SCabacCtx* pCbCtx);
uint8_t* WelsCabacEncodeGetPtr (SCabacCtx* pCbCtx);
int32_t WriteBlockResidualCabac (void* pEncCtx, int16_t* pCoffLevel, int32_t iEndIdx,
int32_t iCalRunLevelFlag,
int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs);
}
#endif

View File

@@ -48,30 +48,30 @@
namespace WelsEnc {
enum EResidualProperty {
LUMA_DC = 0,
LUMA_AC = 1,
LUMA_4x4 = 2,
CHROMA_DC = 3,
CHROMA_AC = 4
enum ECtxBlockCat {
LUMA_DC = 0,
LUMA_AC = 1,
LUMA_4x4 = 2,
CHROMA_DC = 3,
CHROMA_AC = 4
};
#define LUMA_DC_AC 0x04
typedef struct TagCavlcTableItem {
uint16_t uiBits;
uint8_t uiLen;
uint8_t uiSuffixLength;
uint16_t uiBits;
uint8_t uiLen;
uint8_t uiSuffixLength;
} SCavlcTableItem;
void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag);
void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag,int32_t iEntropyCodingModeFlag);
int32_t WriteBlockResidualCavlc (SWelsFuncPtrList* pFuncList, int16_t* pCoffLevel, int32_t iEndIdx,
int32_t iCalRunLevelFlag,
int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs);
#if defined(__cplusplus)
extern "C" {
#endif//__cplusplus

View File

@@ -42,7 +42,7 @@
#include "parameter_sets.h"
#include "svc_enc_slice_segment.h"
#include "bit_stream.h"
#include "set_mb_syn_cabac.h"
namespace WelsEnc {
@@ -178,6 +178,10 @@ uint8_t uiAssumeLog2BytePerMb;
uint32_t uiSliceFMECostDown;//TODO: for FME switch under MT, to opt after ME final?
uint8_t uiReservedFillByte; // reserved to meet 4 bytes alignment
SCabacCtx sCabacCtx;
int32_t iCabacInitIdc;
int32_t iMbSkipRun;
} SSlice, *PSlice;
}

View File

@@ -171,7 +171,6 @@ pBs->pBufPtr += 4 - pBs->iLeftBits / 8;
pBs->iLeftBits = 32;
pBs->uiCurBits = 0; // for future writing safe, 5/19/2010
}
/*
* Write unsigned exp golomb codes
*/
@@ -246,5 +245,15 @@ static inline int32_t BsGetBitsPos (SBitStringAux* pBs) {
return (int32_t) (((pBs->pBufPtr - pBs->pBuf) << 3) + 32 - pBs->iLeftBits);
}
static inline void BsAlign( SBitStringAux* pBs )
{
if( pBs->iLeftBits&7 )
{
pBs->uiCurBits <<= pBs->iLeftBits&7;
pBs->uiCurBits |= (1 << (pBs->iLeftBits&7)) - 1;
pBs->iLeftBits &= ~7;
}
BsFlush(pBs );
}
}
#endif//WELS_EXPONENTIAL_GOLOMB_ENTROPY_CODING_H__

View File

@@ -68,8 +68,12 @@ SMVUnitXY sP16x16Mv;
uint8_t uiLumaQp; // uiLumaQp: pPps->iInitialQp + sSliceHeader->delta_qp + mb->dquant.
uint8_t uiChromaQp;
uint8_t uiSliceIdc; // AVC: pFirstMbInSlice?; SVC: (pFirstMbInSlice << 7) | ((uiDependencyId << 4) | uiQualityId);
uint8_t reserved_filling_bytes[1]; // filling bytes reserved to make structure aligned with 4 bytes, higher cache hit on less structure size by 2 cache lines( 2 * 64 bytes) once hit
uint16_t uiSliceIdc; // 2^16=65536 > MaxFS(36864) of level 5.1; AVC: pFirstMbInSlice?; SVC: (pFirstMbInSlice << 7) | ((uiDependencyId << 4) | uiQualityId);
uint32_t uiChromPredMode;
int32_t iLumaDQp;
SMVUnitXY sMvd[4];
int32_t iCbpDc;
//uint8_t reserved_filling_bytes[1]; // not deleting this line for further changes of this structure. filling bytes reserved to make structure aligned with 4 bytes, higher cache hit on less structure size by 2 cache lines( 2 * 64 bytes) once hit
} SMB, *PMb;
}

View File

@@ -46,6 +46,8 @@
#include "memory_align.h"
#include "codec_app_def.h"
#include "set_mb_syn_cabac.h"
namespace WelsEnc {
@@ -78,7 +80,7 @@ int16_t iMbWidth; /* width of picture size in mb */
int16_t iMbHeight; /* height of picture size in mb */
int16_t iSliceNumInFrame; /* count number of slices in frame; */
int32_t iMbNumInFrame; /* count number of MBs in frame */
uint8_t* pOverallMbMap; /* overall MB map in frame, store virtual slice idc; */
uint16_t* pOverallMbMap; /* overall MB map in frame, store virtual slice idc; */
int16_t* pFirstMbInSlice; /* first MB address top-left based in every slice respectively; */
int32_t* pCountMbNumInSlice; /* count number of MBs in every slice respectively; */
uint32_t uiSliceSizeConstraint;/*in byte*/
@@ -90,10 +92,11 @@ typedef struct TagDynamicSlicingStack {
int32_t iStartPos;
int32_t iCurrentPos;
uint8_t* pBsStackBufPtr; // current writing position
uint8_t* pBsStackBufPtr; // current writing position
uint32_t uiBsStackCurBits;
int32_t iBsStackLeftBits;
SCabacCtx sStoredCabac;
int32_t iMbSkipRunStack;
uint8_t uiLastMbQp;
} SDynamicSlicingStack;
@@ -137,7 +140,7 @@ void UninitSlicePEncCtx (SSliceCtx* pSliceCtx, CMemoryAlign* pMa);
*
* \return uiSliceIdc - successful; (uint8_t)(-1) - failed;
*/
uint8_t WelsMbToSliceIdc (SSliceCtx* pSliceCtx, const int16_t kiMbXY);
uint16_t WelsMbToSliceIdc (SSliceCtx* pSliceCtx, const int16_t kiMbXY);
/*!
* \brief Get first mb in slice/slice_group: uiSliceIdc (apply in Single/multiple slices and FMO)
@@ -193,8 +196,8 @@ bool CheckFixedSliceNumMultiSliceSetting (const int32_t kiMbNumInFrame, SSliceA
bool CheckRasterMultiSliceSetting (const int32_t kiMbNumInFrame, SSliceArgument* pSliceArg);
bool CheckRowMbMultiSliceSetting (const int32_t kiMbWidth, SSliceArgument* pSliceArg);
void GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, uint32_t* pSliceNum);
void GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArg);
bool GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, uint32_t* pSliceNum);
bool GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArg);
//end of checking valid para
int32_t DynamicAdjustSlicePEncCtxAll (SSliceCtx* pSliceCtx,

View File

@@ -342,12 +342,9 @@ pMvMax->iMvX = WELS_MIN (((kiMbWidth - kiMbX) << 4) - INTPEL_NEEDED_MARGIN, kiMa
pMvMax->iMvY = WELS_MIN (((kiMbHeight - kiMbY) << 4) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
}
inline bool CheckMvInRange (const int16_t kiCurrentMv, const int16_t kiMinMv, const int16_t kiMaxMv) {
return ((kiCurrentMv >= kiMinMv) && (kiCurrentMv < kiMaxMv));
}
inline bool CheckMvInRange (const SMVUnitXY ksCurrentMv, const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv) {
return (CheckMvInRange (ksCurrentMv.iMvX, ksMinMv.iMvX, ksMaxMv.iMvX)
&& CheckMvInRange (ksCurrentMv.iMvY, ksMinMv.iMvY, ksMaxMv.iMvY));
return (CheckInRangeCloseOpen (ksCurrentMv.iMvX, ksMinMv.iMvX, ksMaxMv.iMvX)
&& CheckInRangeCloseOpen (ksCurrentMv.iMvY, ksMinMv.iMvY, ksMaxMv.iMvY));
}
//FME switch related
inline bool CalcFMESwitchFlag (const uint8_t uiFMEGoodFrameCount, const int32_t iHighFreMbPrecentage,

View File

@@ -0,0 +1,68 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* \file svc_set_mb_syn.h
*
* \brief Seting all syntax elements of mb and encoding residual with cavlc and cabac
*
* \date 2009.8.12 Created
*
*************************************************************************************
*/
#ifndef SVC_SET_MB_SYN_H_
#define SVC_SET_MB_SYN_H_
#include "typedefs.h"
#include "wels_common_basis.h"
#include "encoder_context.h"
#include "md.h"
#include "slice.h"
#include "set_mb_syn_cavlc.h"
#include "set_mb_syn_cabac.h"
namespace WelsEnc {
int32_t WelsWriteMbResidual (SWelsFuncPtrList* pFuncList, SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs);
void WelsSpatialWriteSubMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
void WelsSpatialWriteMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
void WelsInitSliceCabac(sWelsEncCtx* pEncCtx,SSlice* pSlice);
void WelsCabacInit(void *pCtx);
void WelsWriteSliceEndSyn(SSlice *pSlice,bool bEntropyCodingModeFlag);
//for Base Layer CAVLC writing
int32_t WelsSpatialWriteMbSyn (void* Ctx, SSlice* pSlice, SMB* pCurMb);
int32_t WelsSpatialWriteMbSynCabac (void* pCtx, SSlice* pSlice, SMB* pCurMb);
}
#endif

View File

@@ -37,7 +37,6 @@
*
*************************************************************************************
*/
#ifndef SVC_SET_MB_SYN_CAVLC_H_
#define SVC_SET_MB_SYN_CAVLC_H_
@@ -45,19 +44,24 @@
#include "wels_common_basis.h"
#include "encoder_context.h"
#include "md.h"
#include "slice.h"
#include "set_mb_syn_cavlc.h"
#include "set_mb_syn_cabac.h"
namespace WelsEnc {
int32_t WelsWriteMbResidual (SWelsFuncPtrList* pFuncList, SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs);
void WelsSpatialWriteSubMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
void WelsSpatialWriteMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
void WelsInitSliceCabac(sWelsEncCtx* pEncCtx,SSlice* pSlice);
void WelsWriteSliceEndSyn(SSlice *pSlice,bool bEntropyCodingModeFlag);
//for Base Layer CAVLC writing
int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
int32_t WelsSpatialWriteMbSyn (void* Ctx, SSlice* pSlice, SMB* pCurMb);
int32_t WelsSpatialWriteMbSynCabac (void* pCtx, SSlice* pSlice, SMB* pCurMb);
}
#endif

View File

@@ -47,40 +47,45 @@ namespace WelsEnc {
struct SMVUnitXY { // each 4 Bytes
int16_t iMvX;
int16_t iMvY;
int16_t iMvX;
int16_t iMvY;
public:
SMVUnitXY& sDeltaMv (const SMVUnitXY& _v0, const SMVUnitXY& _v1) {
iMvX = _v0.iMvX - _v1.iMvX;
iMvY = _v0.iMvY - _v1.iMvY;
return (*this);
}
SMVUnitXY& sDeltaMv (const SMVUnitXY& _v0, const SMVUnitXY& _v1) {
iMvX = _v0.iMvX - _v1.iMvX;
iMvY = _v0.iMvY - _v1.iMvY;
return (*this);
};
SMVUnitXY& sAssginMv (const SMVUnitXY& _v0) {
iMvX = _v0.iMvX;
iMvY = _v0.iMvY;
return (*this);
};
};
typedef struct TagMVComponentUnit { // each LIST_0/LIST_1
SMVUnitXY sMotionVectorCache[5 * 6 - 1]; // Luma only: 5 x 6 - 1 = 29 D-Words
int8_t iRefIndexCache[5 * 6]; // Luma only: 5 x 6 = 30 bytes
SMVUnitXY sMotionVectorCache[5 * 6 - 1]; // Luma only: 5 x 6 - 1 = 29 D-Words
int8_t iRefIndexCache[5 * 6]; // Luma only: 5 x 6 = 30 bytes
} SMVComponentUnit, *PMVComponentUnit;
typedef struct TagParaSetOffsetVariable {
int32_t iParaSetIdDelta[MAX_DQ_LAYER_NUM/*+1*/]; //mark delta between SPS_ID_in_bs and sps_id_in_encoder, can be minus, for each dq-layer
int32_t iParaSetIdDelta[MAX_DQ_LAYER_NUM/*+1*/]; //mark delta between SPS_ID_in_bs and sps_id_in_encoder, can be minus, for each dq-layer
//need not extra +1 due no MGS and FMO case so far
bool bUsedParaSetIdInBs[MAX_PPS_COUNT]; //mark the used SPS_ID with 1
uint32_t uiNextParaSetIdToUseInBs; //mark the next SPS_ID_in_bs, for all layers
bool bUsedParaSetIdInBs[MAX_PPS_COUNT]; //mark the used SPS_ID with 1
uint32_t uiNextParaSetIdToUseInBs; //mark the next SPS_ID_in_bs, for all layers
} SParaSetOffsetVariable;
typedef struct TagParaSetOffset {
//in PS0 design, "sParaSetOffsetVariable" record the previous paras before current IDR, AND NEED to be stacked and recover across IDR
SParaSetOffsetVariable
sParaSetOffsetVariable[PARA_SET_TYPE]; //PARA_SET_TYPE=3; paraset_type = 0: AVC_SPS; =1: Subset_SPS; =2: PPS
SParaSetOffsetVariable
sParaSetOffsetVariable[PARA_SET_TYPE]; //PARA_SET_TYPE=3; paraset_type = 0: AVC_SPS; =1: Subset_SPS; =2: PPS
//in PSO design, "bPpsIdMappingIntoSubsetsps" uses the current para of current IDR period
bool
bPpsIdMappingIntoSubsetsps[MAX_DQ_LAYER_NUM/*+1*/]; // need not extra +1 due no MGS and FMO case so far
uint16_t
uiIdrPicId; // IDR picture id: [0, 65535], this one is used for LTR!! Can we just NOT put this into the SParaSetOffset structure?!!
bool
bPpsIdMappingIntoSubsetsps[MAX_DQ_LAYER_NUM/*+1*/]; // need not extra +1 due no MGS and FMO case so far
uint16_t
uiIdrPicId; // IDR picture id: [0, 65535], this one is used for LTR!! Can we just NOT put this into the SParaSetOffset structure?!!
#if _DEBUG
bool bEnableSpsPpsIdAddition;
bool bEnableSpsPpsIdAddition;
#endif
} SParaSetOffset;
@@ -88,32 +93,32 @@ bool bEnableSpsPpsIdAddition;
/* Position Offset structure */
typedef struct TagCropOffset {
int16_t iCropLeft;
int16_t iCropRight;
int16_t iCropTop;
int16_t iCropBottom;
int16_t iCropLeft;
int16_t iCropRight;
int16_t iCropTop;
int16_t iCropBottom;
} SCropOffset;
/* Transform Type */
enum ETransType {
T_4x4 = 0,
T_8x8 = 1,
T_16x16 = 2,
T_PCM = 3
T_4x4 = 0,
T_8x8 = 1,
T_16x16 = 2,
T_PCM = 3
};
enum EMbPosition {
LEFT_MB_POS = 0x01, // A
TOP_MB_POS = 0x02, // B
TOPRIGHT_MB_POS = 0x04, // C
TOPLEFT_MB_POS = 0x08, // D,
RIGHT_MB_POS = 0x10, // add followed four case to reuse when intra up-sample
BOTTOM_MB_POS = 0x20, //
BOTTOMRIGHT_MB_POS = 0x40, //
BOTTOMLEFT_MB_POS = 0x80, //
MB_POS_A = 0x100
LEFT_MB_POS = 0x01, // A
TOP_MB_POS = 0x02, // B
TOPRIGHT_MB_POS = 0x04, // C
TOPLEFT_MB_POS = 0x08, // D,
RIGHT_MB_POS = 0x10, // add followed four case to reuse when intra up-sample
BOTTOM_MB_POS = 0x20, //
BOTTOMRIGHT_MB_POS = 0x40, //
BOTTOMLEFT_MB_POS = 0x80, //
MB_POS_A = 0x100
};
#define MB_ON_PIC_BOUNDRY (RIGHT_MB_POS|BOTTOM_MB_POS|LEFT_MB_POS|TOP_MB_POS)
@@ -180,13 +185,13 @@ typedef uint32_t Mb_Type;
enum {
Intra4x4 = 0,
Intra16x16 = 1,
Inter16x16 = 2,
Inter16x8 = 3,
Inter8x16 = 4,
Inter8x8 = 5,
PSkip = 6
Intra4x4 = 0,
Intra16x16 = 1,
Inter16x16 = 2,
Inter16x8 = 3,
Inter8x16 = 4,
Inter8x8 = 5,
PSkip = 6
};

View File

@@ -160,9 +160,10 @@ typedef void (*PLineFullSearchFunc) (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
const int16_t kiMinMv, const int16_t kiMaxMv,
const bool bVerticalSearch);
typedef void (*PInitializeHashforFeatureFunc) (uint32_t* pTimesOfFeatureValue, uint16_t* pBuf, const int32_t kiListSize,
uint16_t** pLocationOfFeature, uint16_t** pFeatureValuePointerList);
typedef void (*PFillQpelLocationByFeatureValueFunc) (uint16_t* pFeatureOfBlock, const int32_t kiWidth, const int32_t kiHeight,
uint16_t** pFeatureValuePointerList);
uint16_t** pLocationOfFeature, uint16_t** pFeatureValuePointerList);
typedef void (*PFillQpelLocationByFeatureValueFunc) (uint16_t* pFeatureOfBlock, const int32_t kiWidth,
const int32_t kiHeight,
uint16_t** pFeatureValuePointerList);
typedef void (*PCalculateBlockFeatureOfFrame) (uint8_t* pRef, const int32_t kiWidth, const int32_t kiHeight,
const int32_t kiRefStride,
uint16_t* pFeatureOfBlock, uint32_t pTimesOfFeatureValue[]);
@@ -200,6 +201,9 @@ typedef void (*PAfterBuildRefListFunc) (void* pCtx);
typedef int32_t (*PCavlcParamCalFunc) (int16_t* pCoff, uint8_t* pRun, int16_t* pLevel, int32_t* pTotalCoeffs,
int32_t iEndIdx);
typedef int32_t (*PWelsSpatialWriteMbSyn) (void* pCtx, SSlice* pSlice, SMB* pCurMb);
typedef void (*PStashMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun);
typedef int32_t (*PStashPopMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice);
struct TagWelsFuncPointerList {
SExpandPicFunc sExpandPicFunc;
@@ -297,6 +301,9 @@ struct TagWelsFuncPointerList {
PAfterBuildRefListFunc pAfterBuildRefList;
PCavlcParamCalFunc pfCavlcParamCal;
PWelsSpatialWriteMbSyn pfWelsSpatialWriteMbSyn;
PStashMBStatus pfStashMBStatus;
PStashPopMBStatus pfStashPopMBStatus;
};
} //end of namespace WelsEnc {

View File

@@ -106,7 +106,8 @@ typedef struct {
typedef struct SVAAFrameInfoExt_t: public SVAAFrameInfo {
SComplexityAnalysisScreenParam sComplexityScreenParam;
SScrollDetectionParam sScrollDetectInfo;
SRefInfoParam sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT]; //TOP3_BEST_REF_NO_TID
SRefInfoParam sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT];
SRefInfoParam sVaaLtrBestRefCandidate[MAX_REF_PIC_COUNT];
int32_t iNumOfAvailableRef;
int32_t iVaaBestRefFrameNum;
@@ -127,7 +128,7 @@ class CWelsPreProcess {
int32_t AnalyzeSpatialPic (sWelsEncCtx* pEncCtx, const int32_t kiDIdx);
int32_t UpdateSpatialPictures (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam, const int8_t iCurTid,
const int32_t d_idx);
int32_t GetRefFrameInfo (int32_t iRefIdx, SPicture*& pRefOri);
int32_t GetRefFrameInfo (int32_t iRefIdx, bool bCurrentFrameIsSceneLtr, SPicture*& pRefOri);
void AnalyzePictureComplexity (sWelsEncCtx* pCtx, SPicture* pCurPicture, SPicture* pRefPicture,
const int32_t kiDependencyId, const bool kbCalculateBGD);
int32_t UpdateBlockIdcForScreen (uint8_t* pCurBlockStaticPointer, const SPicture* kpRefPic, const SPicture* kpSrcPic);

View File

@@ -73,7 +73,19 @@ static inline int32_t WelsCheckLevelLimitation (const SWelsSPS* kpSps, const SLe
return 1;
}
int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer) {
int32_t iLevel = (int32_t)pSpatialLayer->uiLevelIdc;
int32_t iMaxBitrate = pSpatialLayer->iMaxSpatialBitrate;
while (iLevel <= LEVEL_5_2) {
int32_t iLevelMaxBitrate = g_ksLevelLimits[pSpatialLayer->uiLevelIdc - 1].uiMaxBR * CpbBrNalFactor;
if (iMaxBitrate < iLevelMaxBitrate) {
pSpatialLayer->uiLevelIdc = (ELevelIdc)iLevel;
return 0;
}
iLevel++;
}
return 1;
}
int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
int32_t i = 0;
int32_t iRefFrame = 1;
@@ -266,7 +278,7 @@ int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaS
}
#endif
BsWriteOneBit (pLocalBitStringAux, false/*pPps->entropy_coding_mode_flag*/);
BsWriteOneBit (pLocalBitStringAux, pPps->bEntropyCodingModeFlag);
BsWriteOneBit (pLocalBitStringAux, false/*pPps->bPicOrderPresentFlag*/);
#ifdef DISABLE_FMO_FEATURE
@@ -347,7 +359,8 @@ static inline bool WelsGetPaddingOffset (int32_t iActualWidth, int32_t iActualHe
}
int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialLayerInternal* pLayerParamInternal,
const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc) {
const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
const int32_t kiDlayerCount) {
memset (pSps, 0, sizeof (SWelsSPS));
pSps->uiSpsId = kuiSpsId;
@@ -383,6 +396,16 @@ int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialL
pSps->iLevelIdc = 11;
pSps->bConstraintSet3Flag = true;
}
if (pLayerParam->uiProfileIdc == PRO_BASELINE) {
pSps->bConstraintSet0Flag = true;
}
if (pLayerParam->uiProfileIdc <= PRO_MAIN) {
pSps->bConstraintSet1Flag = true;
}
if (kiDlayerCount > 1) {
pSps->bConstraintSet2Flag = true;
}
return 0;
}
@@ -396,7 +419,7 @@ int32_t WelsInitSubsetSps (SSubsetSps* pSubsetSps, SSpatialLayerConfig* pLayerPa
memset (pSubsetSps, 0, sizeof (SSubsetSps));
WelsInitSps (pSps, pLayerParam, pLayerParamInternal, kuiIntraPeriod, kiNumRefFrame, kuiSpsId, kbEnableFrameCropping,
bEnableRc);
bEnableRc, 1);
pSps->uiProfileIdc = (pLayerParam->uiProfileIdc >= PRO_SCALABLE_BASELINE) ? pLayerParam->uiProfileIdc :
PRO_SCALABLE_BASELINE;
@@ -414,7 +437,8 @@ int32_t WelsInitPps (SWelsPPS* pPps,
SSubsetSps* pSubsetSps,
const uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps) {
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag) {
SWelsSPS* pUsedSps = NULL;
if (pPps == NULL || (pSps == NULL && pSubsetSps == NULL))
return 1;
@@ -433,6 +457,7 @@ int32_t WelsInitPps (SWelsPPS* pPps,
/* fill picture parameter set syntax */
pPps->iPpsId = kuiPpsId;
pPps->iSpsId = pUsedSps->uiSpsId;
pPps->bEntropyCodingModeFlag = kbEntropyCodingModeFlag;
#if !defined(DISABLE_FMO_FEATURE)
pPps->uiNumSliceGroups = 1; //param->qos_param.sliceGroupCount;
if (pPps->uiNumSliceGroups > 1) {

View File

@@ -152,8 +152,9 @@ void WelsInitBGDFunc (SWelsFuncPtrList* pFuncList, const bool kbEnableBackground
* \param pEncCtx sWelsEncCtx*
* \return successful - 0; otherwise none 0 for failed
*/
int32_t InitFunctionPointers (SWelsFuncPtrList* pFuncList, SWelsSvcCodingParam* pParam, uint32_t uiCpuFlag) {
int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam, uint32_t uiCpuFlag) {
int32_t iReturn = ENC_RETURN_SUCCESS;
SWelsFuncPtrList* pFuncList = pEncCtx->pFuncList;
bool bScreenContent = (SCREEN_CONTENT_REAL_TIME == pParam->iUsageType);
/* Functionality utilization of CPU instructions dependency */
@@ -209,7 +210,7 @@ int32_t InitFunctionPointers (SWelsFuncPtrList* pFuncList, SWelsSvcCodingParam*
/*init pixel average function*/
/*get one column or row pixel when refinement*/
WelsInitMcFuncs (pFuncList, uiCpuFlag);
InitCoeffFunc (pFuncList, uiCpuFlag);
InitCoeffFunc (pFuncList,uiCpuFlag,pParam->iEntropyCodingModeFlag);
WelsInitEncodingFuncs (pFuncList, uiCpuFlag);
WelsInitReconstructionFuncs (pFuncList, uiCpuFlag);

View File

@@ -54,6 +54,7 @@
#include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms
#include "slice_multi_threading.h"
#include "measure_time.h"
#include "svc_set_mb_syn.h"
namespace WelsEnc {
@@ -69,6 +70,47 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
);
int32_t WelsBitRateVerification (SLogContext* pLogCtx, SSpatialLayerConfig* pLayerParam, int32_t iLayerId) {
if (pLayerParam->iSpatialBitrate <= 0) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in layer %d, bitrate= %d", iLayerId,
pLayerParam->iSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pLayerParam->iMaxSpatialBitrate == pLayerParam->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_INFO,
"Setting MaxSpatialBitrate (%d) the same at SpatialBitrate (%d) will make the actual bit rate lower than SpatialBitrate",
pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
}
int32_t iLevelMaxBitrate = g_ksLevelLimits[pLayerParam->uiLevelIdc - 1].uiMaxBR * CpbBrNalFactor;
if (pLayerParam->iMaxSpatialBitrate == UNSPECIFIED_BIT_RATE) {
pLayerParam->iMaxSpatialBitrate = iLevelMaxBitrate;
WelsLog (pLogCtx, WELS_LOG_INFO, "Current MaxSpatialBitrate is zero,Get this value from level limitation(%d)",
pLayerParam->iMaxSpatialBitrate);
}
if (pLayerParam->iMaxSpatialBitrate > iLevelMaxBitrate) {
ELevelIdc iCurLevel = pLayerParam->uiLevelIdc;
if (WelsAdjustLevel (pLayerParam)) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"MaxSpatialBitrate (%d) is larger that the limitation LEVEL_5_2, considering it as error setting",
pLayerParam->iMaxSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
} else {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"Level is changed from (%d) to (%d) according to the maxbitrate",
iCurLevel, pLayerParam->uiLevelIdc);
}
}
if (pLayerParam->iMaxSpatialBitrate < pLayerParam->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"MaxSpatialBitrate (%d) should be larger than SpatialBitrate (%d), considering it as error setting",
pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
}
return ENC_RETURN_SUCCESS;
}
/*!
* \brief validate checking in parameter configuration
* \pParam pParam SWelsSvcCodingParam*
@@ -149,17 +191,9 @@ int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) {
for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
SSpatialLayerConfig* pSpatialLayer = &pCfg->sSpatialLayers[i];
iTotalBitrate += pSpatialLayer->iSpatialBitrate;
if (pSpatialLayer->iSpatialBitrate <= 0) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in layer %d, bitrate= %d", i,
pSpatialLayer->iSpatialBitrate);
if (WelsBitRateVerification (pLogCtx, pSpatialLayer, i) != ENC_RETURN_SUCCESS)
return ENC_RETURN_INVALIDINPUT;
}
if (pSpatialLayer->iMaxSpatialBitrate < pSpatialLayer->iSpatialBitrate * 1.1f) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"MaxSpatialBitrate (%d) should set be larger than 1.1 times of SpatialBitrate (%d)",
pSpatialLayer->iMaxSpatialBitrate, pSpatialLayer->iSpatialBitrate);
// pSpatialLayer->iSpatialBitrate = (int32_t) (pSpatialLayer->iMaxSpatialBitrate/1.1f);
}
}
if (iTotalBitrate > pCfg->iTargetBitrate) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
@@ -306,11 +340,20 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
break;
}
if (pCodingParam->iRCMode != RC_OFF_MODE) { // multiple slices verify with gom
//check uiSliceNum
GomValidCheckSliceNum (iMbWidth, iMbHeight, &pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum);
//check uiSliceNum and set uiSliceMbNum with current uiSliceNum
if (!GomValidCheckSliceNum (iMbWidth, iMbHeight, &pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParamValidationExt(), unsupported setting with Resolution and uiSliceNum combination under RC on! So uiSliceNum is changed to %d!",
pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum);
}
if (pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum <= 1 ||
!GomValidCheckSliceMbNum (iMbWidth, iMbHeight, &pSpatialLayer->sSliceCfg.sSliceArgument)) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"ParamValidationExt(), unsupported setting with Resolution and uiSliceNum (%d) combination under RC on! Consider setting single slice with this resolution!",
pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum);
return ENC_RETURN_UNSUPPORTED_PARA;
}
assert (pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum > 1);
//set uiSliceMbNum with current uiSliceNum
GomValidCheckSliceMbNum (iMbWidth, iMbHeight, &pSpatialLayer->sSliceCfg.sSliceArgument);
} else if (!CheckFixedSliceNumMultiSliceSetting (iMbNumInFrame,
&pSpatialLayer->sSliceCfg.sSliceArgument)) { // verify interleave mode settings
//check uiSliceMbNum with current uiSliceNum
@@ -460,8 +503,7 @@ void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam) {
}
}
void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
//TODO (Sijia): this is a temporary solution which keep the ratio between layers
//but it is also possible to fulfill the bitrate of lower layer first
@@ -479,10 +521,15 @@ void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam,
pLayerParam = & (pParam->sSpatialLayers[i]);
fRatio = pLayerParam->iSpatialBitrate / (static_cast<float> (iOrigTotalBitrate));
pLayerParam->iSpatialBitrate = static_cast<int32_t> (pParam->iTargetBitrate * fRatio);
}
}
}
if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS)
return ENC_RETURN_UNSUPPORTED_PARA;
}
} else {
return WelsBitRateVerification (pLogCtx, & (pParam->sSpatialLayers[iLayer]), iLayer);
}
return ENC_RETURN_SUCCESS;
}
/*!
* \brief acquire count number of layers and NALs based on configurable paramters dependency
* \pParam pCtx sWelsEncCtx*
@@ -587,7 +634,7 @@ static void InitMbInfo (sWelsEncCtx* pEnc, SMB* pList, SDqLayer* pLayer, con
bool bLeftTop;
bool bRightTop;
int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
uint8_t uiSliceIdc;
uint16_t uiSliceIdc;
pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx];
pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx];
@@ -732,6 +779,35 @@ void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) {
}
}
int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t kiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps) {
int32_t iRet = 0;
if (!kbUseSubsetSps) {
pSps = & (pCtx->pSpsArray[kiSpsId]);
} else {
pSubsetSps = & (pCtx->pSubsetArray[kiSpsId]);
pSps = &pSubsetSps->pSps;
}
SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
// Need port pSps/pPps initialization due to spatial scalability changed
if (!kbUseSubsetSps) {
iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
} else {
iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
}
return iRet;
}
/*!
* \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
@@ -921,33 +997,13 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
pDqIdc->uiSpatialId = iDlayerIndex;
WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
iDlayerCount, iSpsId, pSps, pSubsetSps);
pPps = & (*ppCtx)->pPPSArray[iPpsId];
if (!bUseSubsetSps) {
pSps = & (*ppCtx)->pSpsArray[iSpsId];
} else {
pSubsetSps = & (*ppCtx)->pSubsetArray[iSpsId];
pSps = &pSubsetSps->pSps;
}
// Need port pSps/pPps initialization due to spatial scalability changed
if (!bUseSubsetSps) {
WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
if (iDlayerCount > 1) {
pSps->bConstraintSet0Flag = true;
pSps->bConstraintSet1Flag = true;
pSps->bConstraintSet2Flag = true;
}
} else {
WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
}
// initialize pPps
WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps);
WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
// Not using FMO in SVC coding so far, come back if need FMO
{
@@ -1857,11 +1913,19 @@ int32_t InitSliceSettings (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPar
break;
}
if (pCodingParam->iRCMode != RC_OFF_MODE) { // multiple slices verify with gom
//check uiSliceNum
GomValidCheckSliceNum (kiMbWidth, kiMbHeight, &pDlp->sSliceCfg.sSliceArgument.uiSliceNum);
assert (pDlp->sSliceCfg.sSliceArgument.uiSliceNum > 1);
//set uiSliceMbNum with current uiSliceNum
GomValidCheckSliceMbNum (kiMbWidth, kiMbHeight, &pDlp->sSliceCfg.sSliceArgument);
//check uiSliceNum and set uiSliceMbNum with current uiSliceNum
if (!GomValidCheckSliceNum (kiMbWidth, kiMbHeight, &pDlp->sSliceCfg.sSliceArgument.uiSliceNum)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParamValidationExt(), unsupported setting with Resolution and uiSliceNum combination under RC on! So uiSliceNum is changed to %d!",
pDlp->sSliceCfg.sSliceArgument.uiSliceNum);
}
if (pDlp->sSliceCfg.sSliceArgument.uiSliceNum <= 1 ||
!GomValidCheckSliceMbNum (kiMbWidth, kiMbHeight, &pDlp->sSliceCfg.sSliceArgument)) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"ParamValidationExt(), unsupported setting with Resolution and uiSliceNum (%d) combination under RC on! Consider setting single slice with this resolution!",
pDlp->sSliceCfg.sSliceArgument.uiSliceNum);
return ENC_RETURN_INVALIDINPUT;
}
} else if (!CheckFixedSliceNumMultiSliceSetting (kiMbNumInFrame,
&pDlp->sSliceCfg.sSliceArgument)) { // verify interleave mode settings
//check uiSliceMbNum with current uiSliceNum
@@ -1893,7 +1957,7 @@ int32_t InitSliceSettings (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPar
2; // Disable loop filter on slice boundaries since that's not allowed with multithreading
*pMaxSliceCount = iMaxSliceCount;
return 0;
return ENC_RETURN_SUCCESS;
}
/*!
@@ -2053,7 +2117,7 @@ int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPar
FreeMemorySvc (&pCtx);
return 1;
}
InitFunctionPointers (pCtx->pFuncList, pCtx->pSvcParam, uiCpuFeatureFlags);
InitFunctionPointers (pCtx, pCtx->pSvcParam, uiCpuFeatureFlags);
pCtx->iActiveThreadsNum = pCodingParam->iCountThreadsNum;
pCtx->iMaxSliceCount = iSliceNum;
@@ -2064,9 +2128,16 @@ int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPar
return iRet;
}
if (pCodingParam->iMultipleThreadIdc > 1)
if (pCodingParam->iMultipleThreadIdc > 1) {
iRet = CreateSliceThreads (pCtx);
if (iRet != 0) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), CreateSliceThreads failed return %d.", iRet);
FreeMemorySvc (&pCtx);
return iRet;
}
}
if (pCodingParam->iEntropyCodingModeFlag)
WelsCabacInit (pCtx);
WelsRcInitModule (pCtx, pCtx->pSvcParam->iRCMode);
pCtx->pVpp = new CWelsPreProcess (pCtx);
@@ -2248,7 +2319,7 @@ void DynslcUpdateMbNeighbourInfoListForAllSlices (SSliceCtx* pSliceCtx, SMB* pMb
bool bTop;
bool bLeftTop;
bool bRightTop;
int32_t uiSliceIdc;
uint16_t uiSliceIdc;
int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
uiSliceIdc = WelsMbToSliceIdc (pSliceCtx, kiMbXY);
@@ -2323,7 +2394,8 @@ void UpdateSlicepEncCtxWithPartition (SSliceCtx* pSliceCtx, int32_t iPartitionNu
}
pSliceCtx->pFirstMbInSlice[i] = iFirstMbIdx;
memset (pSliceCtx->pOverallMbMap + iFirstMbIdx, (uint8_t)i, pSliceCtx->pCountMbNumInSlice[i]*sizeof (uint8_t));
WelsSetMemMultiplebytes_c (pSliceCtx->pOverallMbMap + iFirstMbIdx, i,
pSliceCtx->pCountMbNumInSlice[i], sizeof (uint16_t));
// for next partition(or pSlice)
iFirstMbIdx += pSliceCtx->pCountMbNumInSlice[i];
@@ -2711,7 +2783,7 @@ void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable,
* \brief write all parameter sets introduced in SVC extension
* \return writing results, success or error
*/
int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal) {
int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal, int32_t* pTotalLength) {
int32_t iSize = 0;
int32_t iNal = 0;
int32_t iIdx = 0;
@@ -2723,6 +2795,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal)
return ENC_RETURN_UNEXPECTED;
*pTotalLength = 0;
/* write all SPS */
iIdx = 0;
while (iIdx < pCtx->iSpsNum) {
@@ -2809,6 +2882,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
}
*pNumNal = iCountNal;
*pTotalLength = iSize;
return ENC_RETURN_SUCCESS;
}
@@ -2919,13 +2993,14 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) {
SFrameBSInfo* pFbi = (SFrameBSInfo*)pDst;
SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0];
int32_t iCountNal = 0;
int32_t iTotalLength = 0;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs;
pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen;
InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize);
pCtx->iPosBsBuffer = 0;
int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal);
int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iTotalLength);
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
pLayerBsInfo->uiSpatialId = 0;
@@ -2961,13 +3036,13 @@ int32_t GetSubSequenceId (sWelsEncCtx* pCtx, EVideoFrameType eFrameType) {
//loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0)
bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
const uint32_t uiTimeStamp) {
const long long uiTimeStamp) {
SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
bool bSkipMustFlag = false;
if (pCtx->pSvcParam->bEnableFrameSkip) {
if ((RC_QUALITY_MODE == pCtx->pSvcParam->iRCMode) || (RC_BITRATE_MODE == pCtx->pSvcParam->iRCMode)) {
for (int32_t i = 0; i < iSpatialNum; i++) {
if (0 == pCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) {
if (UNSPECIFIED_BIT_RATE == pCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) {
break;
}
pCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid;
@@ -3035,27 +3110,26 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
if (iSpatialNum < 1) { // skip due to temporal layer settings (different frame rate)
++ pCtx->iCodingIndex;
pFbi->eFrameType = videoFrameTypeSkip;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %8" PRId64", skip one frame",
(int64_t)pSrcPic->uiTimeStamp);
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
pSrcPic->uiTimeStamp, pFbi->eFrameType);
return ENC_RETURN_SUCCESS;
}
eFrameType = DecideFrameType (pCtx, iSpatialNum);
if (eFrameType == videoFrameTypeSkip) {
pFbi->eFrameType = eFrameType;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %8" PRId64", skip one frame",
(int64_t)pSrcPic->uiTimeStamp);
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
pSrcPic->uiTimeStamp, pFbi->eFrameType);
return ENC_RETURN_SUCCESS;
}
//loop each layer to check if have skip frame when RC and frame skip enable
if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, (uint32_t)pSrcPic->uiTimeStamp)) {
if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, pSrcPic->uiTimeStamp)) {
pFbi->eFrameType = videoFrameTypeSkip;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %8" PRId64", skip one frame",
(int64_t)pSrcPic->uiTimeStamp);
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
pSrcPic->uiTimeStamp, pFbi->eFrameType);
return ENC_RETURN_SUCCESS;
}
InitFrameCoding (pCtx, eFrameType);
iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex,
@@ -3070,7 +3144,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
//if ( pSvcParam->bEnableSSEI )
// write parameter sets bitstream here
pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal);
int32_t iNonVclSize = 0;
pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iNonVclSize);
WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
pLayerBsInfo->uiSpatialId = 0;
@@ -3083,6 +3158,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
++ iLayerNum;
iFrameSize += iNonVclSize;
}
pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid];
@@ -3581,6 +3658,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1;
++ iLayerNum;
iFrameSize += iPaddingNalSize;
}
if ((pParam->sSliceCfg.uiSliceMode == SM_FIXEDSLCNUM_SLICE || pParam->sSliceCfg.uiSliceMode == SM_AUTO_SLICE)
@@ -3644,9 +3723,17 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pCtx->eLastNalPriority = eNalRefIdc;
pFbi->iLayerNum = iLayerNum;
pFbi->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
WelsLog (pLogCtx, WELS_LOG_DEBUG, "WelsEncoderEncodeExt() OutputInfo iLayerNum %d,iSubSeqId = %d,iFrameSize = %d",
iLayerNum,
pFbi->iSubSeqId, iFrameSize);
for (int32_t i = 0; i < iLayerNum; i++)
WelsLog (pLogCtx, WELS_LOG_DEBUG, "WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount %d", i,
pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount);
WelsEmms();
pFbi->eFrameType = eFrameType;
pFbi->iFrameSizeInBytes = iFrameSize;
return ENC_RETURN_SUCCESS;
}
@@ -3900,15 +3987,19 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
iMaxSliceNum *= SLICE_NUM_EXPAND_COEF;
SWelsNalRaw* pNalList = (SWelsNalRaw*)pMA->WelsMalloc (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
if (NULL == pNalList)
if (NULL == pNalList) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::DynSliceRealloc: pNalList is NULL");
return ENC_RETURN_MEMALLOCERR;
}
memcpy (pNalList, pCtx->pOut->sNalList, sizeof (SWelsNalRaw) * pCtx->pOut->iCountNals);
pMA->WelsFree (pCtx->pOut->sNalList, "pOut->sNalList");
pCtx->pOut->sNalList = pNalList;
int32_t* pNalLen = (int32_t*)pMA->WelsMalloc (iCountNals * sizeof (int32_t), "pOut->pNalLen");
if (NULL == pNalLen)
if (NULL == pNalLen) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::DynSliceRealloc: pNalLen is NULL");
return ENC_RETURN_MEMALLOCERR;
}
memcpy (pNalLen, pCtx->pOut->pNalLen, sizeof (int32_t) * pCtx->pOut->iCountNals);
pMA->WelsFree (pCtx->pOut->pNalLen, "pOut->pNalLen");
pCtx->pOut->pNalLen = pNalLen;
@@ -3924,8 +4015,10 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
}
SSlice* pSlice = (SSlice*)pMA->WelsMallocz (sizeof (SSlice) * iMaxSliceNum, "Slice");
if (NULL == pSlice)
if (NULL == pSlice) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::DynSliceRealloc: pSlice is NULL");
return ENC_RETURN_MEMALLOCERR;
}
memcpy (pSlice, pCurLayer->sLayerInfo.pSliceInLayer, sizeof (SSlice) * iMaxSliceNumOld);
int32_t uiSliceIdx;
uiSliceIdx = iMaxSliceNumOld;
@@ -3939,8 +4032,12 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
pSliceIdx->pSliceBsa = &pCtx->pSliceBs[uiSliceIdx].sBsWrite;
else
pSliceIdx->pSliceBsa = &pCtx->pOut->sBsWrite;
if (AllocMbCacheAligned (&pSliceIdx->sMbCacheInfo, pMA))
if (AllocMbCacheAligned (&pSliceIdx->sMbCacheInfo, pMA)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"CWelsH264SVCEncoder::DynSliceRealloc: realloc MbCache not successful at slice_idx=%d (max-slice=%d)",
uiSliceIdx, iMaxSliceNum);
return ENC_RETURN_MEMALLOCERR;
}
pSliceIdx->bSliceHeaderExtFlag = pBaseSlice->bSliceHeaderExtFlag;
pSHExt->sSliceHeader.iPpsId = pBaseSHExt->sSliceHeader.iPpsId;
@@ -3959,8 +4056,10 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
pCurLayer->sLayerInfo.pSliceInLayer = pSlice;
int16_t* pFirstMbInSlice = (int16_t*)pMA->WelsMalloc (iMaxSliceNum * sizeof (int16_t), "pSliceSeg->pFirstMbInSlice");
if (NULL == pFirstMbInSlice)
if (NULL == pFirstMbInSlice) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::DynSliceRealloc: pFirstMbInSlice is NULL");
return ENC_RETURN_MEMALLOCERR;
}
memset (pFirstMbInSlice, 0, sizeof (int16_t) * iMaxSliceNum);
memcpy (pFirstMbInSlice, pCurLayer->pSliceEncCtx->pFirstMbInSlice, sizeof (int16_t) * iMaxSliceNumOld);
pMA->WelsFree (pCurLayer->pSliceEncCtx->pFirstMbInSlice, "pSliceSeg->pFirstMbInSlice");
@@ -3968,8 +4067,11 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
int32_t* pCountMbNumInSlice = (int32_t*)pMA->WelsMalloc (iMaxSliceNum * sizeof (int32_t),
"pSliceSeg->pCountMbNumInSlice");
if (NULL == pCountMbNumInSlice)
if (NULL == pCountMbNumInSlice) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"CWelsH264SVCEncoder::DynSliceRealloc: realloc pCountMbNumInSlice not successful");
return ENC_RETURN_MEMALLOCERR;
}
memcpy (pCountMbNumInSlice, pCurLayer->pSliceEncCtx->pCountMbNumInSlice, sizeof (int32_t) * iMaxSliceNumOld);
uiSliceIdx = iMaxSliceNumOld;
while (uiSliceIdx < iMaxSliceNum) {
@@ -3980,8 +4082,11 @@ int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
pCurLayer->pSliceEncCtx->pCountMbNumInSlice = pCountMbNumInSlice;
SRCSlicing* pSlcingOverRc = (SRCSlicing*)pMA->WelsMalloc (iMaxSliceNum * sizeof (SRCSlicing), "SlicingOverRC");
if (NULL == pSlcingOverRc)
if (NULL == pSlcingOverRc) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"CWelsH264SVCEncoder::DynSliceRealloc: realloc pSlcingOverRc not successful");
return ENC_RETURN_MEMALLOCERR;
}
memcpy (pSlcingOverRc, pCtx->pWelsSvcRc->pSlicingOverRc, sizeof (SRCSlicing) * iMaxSliceNumOld);
uiSliceIdx = iMaxSliceNumOld;
SRCSlicing* pSORC = &pSlcingOverRc[uiSliceIdx];
@@ -4045,9 +4150,16 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
if (iSliceIdx >= (pSliceCtx->iMaxSliceNumConstraint - kiSliceIdxStep)) { // insufficient memory in pSliceInLayer[]
if (pCtx->iActiveThreadsNum == 1) {
if (DynSliceRealloc (pCtx, pFrameBSInfo, pLayerBsInfo)) //only single thread support re-alloc now
//only single thread support re-alloc now
if (DynSliceRealloc (pCtx, pFrameBSInfo, pLayerBsInfo)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"CWelsH264SVCEncoder::WelsCodeOnePicPartition: DynSliceRealloc not successful");
return ENC_RETURN_MEMALLOCERR;
}
} else if (iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"CWelsH264SVCEncoder::WelsCodeOnePicPartition: iSliceIdx(%d) over iMaxSliceNumConstraint(%d)", iSliceIdx,
pSliceCtx->iMaxSliceNumConstraint);
return ENC_RETURN_MEMALLOCERR;
}
}

View File

@@ -53,12 +53,6 @@ namespace WelsEnc {
#define VIRTUAL_BUFFER_LOW_TH 120 //*INT_MULTIPLY
#define VIRTUAL_BUFFER_HIGH_TH 180 //*INT_MULTIPLY
//#define _TEST_TEMP_RC_
#ifdef _TEST_TEMP_RC_
//#define _NOT_USE_AQ_FOR_TEST_
FILE* fp_test_rc = NULL;
FILE* fp_vgop = NULL;
#endif
#define _BITS_RANGE 0
const int32_t g_kiQpToQstepTable[52] = { 63, 71, 79, 89, 100, 112, 126, 141, 159, 178,
200, 224, 252, 283, 317, 356, 400, 449, 504, 566,
@@ -123,10 +117,6 @@ void RcInitSequenceParameter (sWelsEncCtx* pEncCtx) {
bool bMultiSliceMode = false;
int32_t iGomRowMode0 = 1, iGomRowMode1 = 1;
#ifdef _TEST_TEMP_RC_
fp_test_rc = fopen ("testRC.dat", "w");
fp_vgop = fopen ("vgop.dat", "w");
#endif
for (j = 0; j < pEncCtx->pSvcParam->iSpatialLayerNum; j++) {
SSliceCtx* pSliceCtx = &pEncCtx->pSliceCtxList[j];
pWelsSvcRc = &pEncCtx->pWelsSvcRc[j];
@@ -230,7 +220,7 @@ void RcUpdateBitrateFps (sWelsEncCtx* pEncCtx) {
SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
const int32_t kiGopSize = (1 << pDLayerParamInternal->iDecompositionStages);
const int32_t kiHighestTid = pDLayerParamInternal->iHighestTemporalId;
int32_t input_iBitsPerFrame = WELS_ROUND (pDLayerParam->iSpatialBitrate * INT_MULTIPLY /
int64_t input_iBitsPerFrame = WELS_ROUND64 (((int64_t)pDLayerParam->iSpatialBitrate) * INT_MULTIPLY /
pDLayerParamInternal->fInputFrameRate);
const int32_t kiGopBits = WELS_DIV_ROUND (input_iBitsPerFrame * kiGopSize, INT_MULTIPLY);
int32_t i;
@@ -255,7 +245,7 @@ void RcUpdateBitrateFps (sWelsEncCtx* pEncCtx) {
//change remaining bits
if (pWelsSvcRc->iBitsPerFrame > REMAIN_BITS_TH)
pWelsSvcRc->iRemainingBits = pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame;
pWelsSvcRc->iRemainingBits = (int32_t) (pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame);
pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame;
}
@@ -349,9 +339,6 @@ void RcTraceVGopBitrate (sWelsEncCtx* pEncCtx) {
int32_t iFrameInVGop = pWelsSvcRc->iFrameCodedInVGop + pWelsSvcRc->iSkipFrameInVGop;
if (0 != iFrameInVGop)
iVGopBitrate = WELS_ROUND (iTotalBits / iFrameInVGop * pWelsSvcRc->fFrameRate);
#ifdef _TEST_TEMP_Rc_
fprintf (fp_vgop, "%d\n", WELS_ROUND ((double)iTotalBits / iFrameInVGop));
#endif
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "[Rc] VGOPbitrate%d: %d ", kiDid, iVGopBitrate);
if (iTotalBits > 0) {
iTid = 0;
@@ -510,7 +497,6 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
#ifndef _NOT_USE_AQ_FOR_TEST_
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
iLumaQp = WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp,
@@ -520,7 +506,6 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp);
}
#endif
pEncCtx->iGlobalQp = iLumaQp;
}
@@ -592,12 +577,10 @@ void RcCalculateMbQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, const int32_t kiSliceId
int32_t iLumaQp = pSOverRc->iCalculatedQpSlice;
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
#ifndef _NOT_USE_AQ_FOR_TEST_
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp +
pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinQp, 51);
}
#endif
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)];
pCurMb->uiLumaQp = iLumaQp;
}
@@ -767,9 +750,9 @@ void RcTraceFrameBits (void* pCtx, long long uiTimeStamp) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %8d, Frame type =%d, encoding_qp%d, average qp = %3d, max qp = %3d, min qp = %3d, index = %8d,\
"[Rc] Frame timestamp = %lld, Frame type =%d, encoding_qp%d, average qp = %3d, max qp = %3d, min qp = %3d, index = %8d,\
iTid = %1d, used = %8d, bitsperframe = %8d, target = %8d, remaingbits = %8d, skipbuffersize = %8d",
(uint32_t)uiTimeStamp,pEncCtx->eSliceType, pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp,pWelsSvcRc->iMaxFrameQp,pWelsSvcRc->iMinFrameQp,
uiTimeStamp,pEncCtx->eSliceType, pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp,pWelsSvcRc->iMaxFrameQp,pWelsSvcRc->iMinFrameQp,
pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits,WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY),
pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip);
@@ -905,12 +888,6 @@ void WelsRcPictureInfoUpdateGom (void* pCtx, int32_t iLayerSize) {
if (pEncCtx->pSvcParam->iPaddingFlag)
RcVBufferCalculationPadding (pEncCtx);
pWelsSvcRc->iFrameCodedInVGop++;
#ifdef _TEST_TEMP_Rc_
fprintf (fp_test_rc, "%d\n", pWelsSvcRc->iFrameDqBits);
if (pEncCtx->iSkipFrameFlag)
fprintf (fp_test_rc, "0\n");
fflush (fp_test_rc);
#endif
}
void WelsRcMbInitGom (void* pCtx, SMB* pCurMb, SSlice* pSlice) {
@@ -1216,14 +1193,6 @@ void WelsRcFreeMemory (void* pCtx) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
SWelsSvcRc* pWelsSvcRc = NULL;
int32_t i = 0;
#ifdef _TEST_TEMP_Rc_
if (fp_test_rc)
fclose (fp_test_rc);
fp_test_rc = NULL;
if (fp_vgop)
fclose (fp_vgop);
fp_vgop = NULL;
#endif
for (i = 0; i < pEncCtx->pSvcParam->iSpatialLayerNum; i++) {
pWelsSvcRc = &pEncCtx->pWelsSvcRc[i];
RcFreeLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign);

View File

@@ -106,6 +106,7 @@ static void DeleteNonSceneLTR (sWelsEncCtx* pCtx) {
SPicture* pRef = pRefList->pLongRefList[i];
if (pRef != NULL && pRef->bUsedAsRef && pRef->bIsLongRef && (!pRef->bIsSceneLTR) &&
(pCtx->uiTemporalId < pRef->uiTemporalId || pCtx->bCurFrameMarkedAsSceneLtr)) {
//this is our strategy to Unref all non-sceneLTR when the the current frame is sceneLTR
pRef->SetUnref();
DeleteLTRFromLongList (pCtx, i);
i--;
@@ -310,12 +311,13 @@ static inline void LTRMarkProcessScreen (sWelsEncCtx* pCtx) {
int32_t iLtrIdx = pCtx->pDecPic->iLongTermPicNum;
pCtx->pVaa->uiMarkLongTermPicIdx = pCtx->pDecPic->iLongTermPicNum;
assert (CheckInRangeCloseOpen (iLtrIdx, 0, MAX_REF_PIC_COUNT));
if (pLongRefList[iLtrIdx] != NULL) {
pLongRefList[iLtrIdx]->SetUnref();
DeleteLTRFromLongList (pCtx, iLtrIdx);
} else {
pRefList->uiLongRefCount++;
}
pLongRefList[iLtrIdx] = pCtx->pDecPic;
pRefList->uiLongRefCount++;
}
static void PrefetchNextBuffer (void* pEncCtx) {
@@ -773,7 +775,7 @@ bool WelsBuildRefListScreen (void* pEncCtx, const int32_t iPOC, int32_t iBestLtr
int iLtrRefIdx = 0;
SPicture* pRefOri = NULL;
for (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++) {
iLtrRefIdx = pCtx->pVpp->GetRefFrameInfo (idx, pRefOri);
iLtrRefIdx = pCtx->pVpp->GetRefFrameInfo (idx, pCtx->bCurFrameMarkedAsSceneLtr, pRefOri);
if (iLtrRefIdx >= 0 && iLtrRefIdx <= pParam->iLTRRefNum) {
SPicture* pRefPic = pRefList->pLongRefList[iLtrRefIdx];
if (pRefPic != NULL && pRefPic->bUsedAsRef && pRefPic->bIsLongRef) {
@@ -805,6 +807,29 @@ bool WelsBuildRefListScreen (void* pEncCtx, const int32_t iPOC, int32_t iBestLtr
}
}
} // end of (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++)
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"WelsBuildRefListScreen(), CurrentFramePoc=%d, isLTR=%d", iPOC, pCtx->bCurFrameMarkedAsSceneLtr);
for (int j = 0; j < iNumRef; j++) {
SPicture* pARefPicture = pRefList->pLongRefList[j];
if (pARefPicture != NULL) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"WelsBuildRefListScreen()\tRefLot[%d]: iPoc=%d, iPictureType=%d, bUsedAsRef=%d, bIsLongRef=%d, bIsSceneLTR=%d, uiTemporalId=%d, iFrameNum=%d, iMarkFrameNum=%d, iLongTermPicNum=%d, uiRecieveConfirmed=%d",
j,
pARefPicture->iFramePoc,
pARefPicture->iPictureType,
pARefPicture->bUsedAsRef,
pARefPicture->bIsLongRef,
pARefPicture->bIsSceneLTR,
pARefPicture->uiTemporalId,
pARefPicture->iFrameNum,
pARefPicture->iMarkFrameNum,
pARefPicture->iLongTermPicNum,
pARefPicture->uiRecieveConfirmed);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "WelsBuildRefListScreen()\tRefLot[%d]: NULL", j);
}
}
} else {
// dealing with IDR
WelsResetRefList (pCtx); //for IDR, SHOULD reset pRef list.
@@ -817,6 +842,11 @@ bool WelsBuildRefListScreen (void* pEncCtx, const int32_t iPOC, int32_t iBestLtr
return (pCtx->iNumRef0 > 0 || pCtx->eSliceType == I_SLICE) ? (true) : (false);
}
static inline bool IsValidFrameNum (const int32_t kiFrameNum) {
return (kiFrameNum < (1 << 30)); // TODO: use the original judge first, may be improved
}
void WelsMarkPicScreen (void* pEncCtx) {
#define STR_ROOM 1
sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
@@ -853,7 +883,6 @@ void WelsMarkPicScreen (void* pEncCtx) {
}
}
} else {
int32_t iMinSTRframe_num = 1 << 30; // is big enough
int32_t iRefNum_t[MAX_TEMPORAL_LAYER_NUM] = {0};
for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)) {
@@ -867,11 +896,20 @@ void WelsMarkPicScreen (void* pEncCtx) {
iMaxMultiRefTid = i;
}
}
int32_t iLongestDeltaFrameNum = -1;
int32_t iMaxFrameNum = (1 << pCtx->pSps->uiLog2MaxFrameNum);
for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)
&& iMaxMultiRefTid == ppLongRefList[i]->uiTemporalId) {
if (ppLongRefList[i]->iFrameNum < iMinSTRframe_num) {
assert (IsValidFrameNum (ppLongRefList[i]->iFrameNum)); // pLtr->iCurLtrIdx must have a value
int32_t iDeltaFrameNum = (pCtx->iFrameNum >= ppLongRefList[i]->iFrameNum)
? (pCtx->iFrameNum - ppLongRefList[i]->iFrameNum)
: (pCtx->iFrameNum + iMaxFrameNum - ppLongRefList[i]->iFrameNum);
if (iDeltaFrameNum > iLongestDeltaFrameNum) {
pLtr->iCurLtrIdx = ppLongRefList[i]->iLongTermPicNum;
iLongestDeltaFrameNum = iDeltaFrameNum;
}
}
}

View File

@@ -0,0 +1,240 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* \file set_mb_syn_cabac.cpp
*
* \brief cabac coding engine
*
* \date 10/11/2014 Created
*
*************************************************************************************
*/
#include <string.h>
#include "typedefs.h"
#include "macros.h"
#include "wels_common_defs.h"
#include "set_mb_syn_cabac.h"
#include "encoder.h"
namespace WelsEnc {
void WelsCabacInit (void* pCtx) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
for (int32_t iModel = 0; iModel < 4; iModel++) {
for (int32_t iQp = 0; iQp <= WELS_QP_MAX; iQp++)
for (int32_t iIdx = 0; iIdx < WELS_CONTEXT_COUNT; iIdx++) {
int32_t m = g_kiCabacGlobalContextIdx[iIdx][iModel][0];
int32_t n = g_kiCabacGlobalContextIdx[iIdx][iModel][1];
int32_t iPreCtxState = WELS_CLIP3 ((((m * iQp) >> 4) + n), 1, 126);
uint8_t uiValMps = 0;
uint8_t uiStateIdx = 0;
if (iPreCtxState <= 63) {
uiStateIdx = 63 - iPreCtxState;
uiValMps = 0;
} else {
uiStateIdx = iPreCtxState - 64;
uiValMps = 1;
}
pEncCtx->sWelsCabacContexts[iModel][iQp][iIdx].m_uiState = uiStateIdx;
pEncCtx->sWelsCabacContexts[iModel][iQp][iIdx].m_uiValMps = uiValMps;
}
}
}
void WelsCabacContextInit (void* pCtx, SCabacCtx* pCbCtx, int32_t iModel) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
int32_t iIdx = pEncCtx->eSliceType == WelsCommon::I_SLICE ? 0 : iModel + 1;
int32_t iQp = pEncCtx->iGlobalQp;
memcpy (pCbCtx->m_sStateCtx, pEncCtx->sWelsCabacContexts[iIdx][iQp],
WELS_CONTEXT_COUNT * sizeof (SStateCtx));
}
void WelsCabacEncodeInit (SCabacCtx* pCbCtx, uint8_t* pBuf, uint8_t* pEnd) {
pCbCtx->m_uiLow = 0;
pCbCtx->m_uiRange = 510;
pCbCtx->m_iBitsOutstanding = 0;
pCbCtx->m_uData = 0;
pCbCtx->m_uiBitsUsed = 0;
pCbCtx->m_iFirstFlag = 1;
pCbCtx->m_pBufStart = pBuf;
pCbCtx->m_pBufEnd = pEnd;
pCbCtx->m_pBufCur = pBuf;
pCbCtx->m_uiBinCountsInNalUnits = 0;
}
void WelsCabacPutBit (SCabacCtx* pCbCtx, uint32_t iValue) {
if (pCbCtx->m_iFirstFlag != 0) {
pCbCtx->m_iFirstFlag = 0;
} else {
pCbCtx->m_uData = (pCbCtx->m_uData << 1) | iValue;
pCbCtx->m_uiBitsUsed++;
}
if (pCbCtx->m_iBitsOutstanding == 0) {
while (pCbCtx->m_uiBitsUsed >= 8) {
pCbCtx->m_uiBitsUsed -= 8;
uint32_t uiByte = pCbCtx->m_uData >> (pCbCtx->m_uiBitsUsed);
if (pCbCtx->m_uiBitsUsed == 0)
pCbCtx->m_uData = 0;
else
pCbCtx->m_uData &= (uint32_t) ((0xFFFFFFFF) >> (32 - pCbCtx->m_uiBitsUsed));
*pCbCtx->m_pBufCur ++ = uiByte;
}
} else {
while (pCbCtx->m_iBitsOutstanding > 0) {
pCbCtx->m_uData = (pCbCtx->m_uData << 1) | (1 - iValue);
pCbCtx->m_iBitsOutstanding--;
pCbCtx->m_uiBitsUsed++;
while (pCbCtx->m_uiBitsUsed >= 8) {
pCbCtx->m_uiBitsUsed -= 8;
uint32_t uiByte = pCbCtx->m_uData >> (pCbCtx->m_uiBitsUsed);
if (pCbCtx->m_uiBitsUsed == 0)
pCbCtx->m_uData = 0;
else
pCbCtx->m_uData &= (uint32_t) ((0xFFFFFFFF) >> (32 - pCbCtx->m_uiBitsUsed));
*pCbCtx->m_pBufCur ++ = uiByte;
}
}
}
}
void WelsCabacEncodeRenorm (SCabacCtx* pCbCtx) {
while (pCbCtx->m_uiRange < 256) {
if (pCbCtx->m_uiLow < 256) {
WelsCabacPutBit (pCbCtx, 0);
} else {
if (pCbCtx->m_uiLow >= 512) {
pCbCtx->m_uiLow -= 512;
WelsCabacPutBit (pCbCtx, 1);
} else {
pCbCtx->m_uiLow -= 256;
pCbCtx->m_iBitsOutstanding++;
}
}
pCbCtx->m_uiRange <<= 1;
pCbCtx->m_uiLow <<= 1;
}
}
void WelsCabacEncodeDecision (SCabacCtx* pCbCtx, int32_t iCtx, uint32_t uiBin) {
uint8_t uiState = pCbCtx->m_sStateCtx[iCtx].m_uiState;
uint8_t uiValMps = pCbCtx->m_sStateCtx[iCtx].m_uiValMps;
uint32_t uiRangeLps = g_kuiCabacRangeLps[uiState][ (pCbCtx->m_uiRange >> 6) & 3];
pCbCtx->m_uiRange -= uiRangeLps;
if (uiBin != uiValMps) { //LPS
pCbCtx->m_uiLow += pCbCtx->m_uiRange;
pCbCtx->m_uiRange = uiRangeLps;
if (uiState == 0)
uiValMps = 1 - uiValMps;
pCbCtx->m_sStateCtx[iCtx].m_uiState = g_kuiStateTransTable[uiState][0];
pCbCtx->m_sStateCtx[iCtx].m_uiValMps = uiValMps;
} else {
pCbCtx->m_sStateCtx[iCtx].m_uiState = g_kuiStateTransTable[uiState][1];
}
WelsCabacEncodeRenorm (pCbCtx);
pCbCtx->m_uiBinCountsInNalUnits++;
}
void WelsCabacEncodeBypassOne (SCabacCtx* pCbCtx, uint32_t uiBin) {
pCbCtx->m_uiLow <<= 1;
if (uiBin) {
pCbCtx->m_uiLow += pCbCtx->m_uiRange;
}
if (pCbCtx->m_uiLow >= 1024) {
WelsCabacPutBit (pCbCtx, 1);
pCbCtx->m_uiLow -= 1024;
} else {
if (pCbCtx->m_uiLow < 512)
WelsCabacPutBit (pCbCtx, 0);
else {
pCbCtx->m_uiLow -= 512;
pCbCtx->m_iBitsOutstanding++;
}
}
pCbCtx->m_uiBinCountsInNalUnits++;
}
void WelsCabacEncodeTerminate (SCabacCtx* pCbCtx, uint32_t uiBin) {
pCbCtx->m_uiRange -= 2;
if (uiBin) {
pCbCtx->m_uiLow += pCbCtx->m_uiRange;
pCbCtx->m_uiRange = 2;
WelsCabacEncodeRenorm (pCbCtx);
WelsCabacPutBit (pCbCtx, ((pCbCtx->m_uiLow >> 9) & 1));
int32_t iLastTwoBits = (((pCbCtx->m_uiLow >> 7) & 3) | 1);
pCbCtx->m_uData = (pCbCtx->m_uData << 2) | iLastTwoBits;
pCbCtx->m_uiBitsUsed += 2;
} else {
WelsCabacEncodeRenorm (pCbCtx);
}
pCbCtx->m_uiBinCountsInNalUnits++;
}
void WelsCabacEncodeUeBypass (SCabacCtx* pCbCtx, int32_t iExpBits, uint32_t uiVal) {
int32_t iSufS = uiVal;
int32_t iStopLoop = 0;
int32_t k = iExpBits;
do {
if (iSufS >= (1 << k)) {
WelsCabacEncodeBypassOne (pCbCtx, 1);
iSufS = iSufS - (1 << k);
k++;
} else {
WelsCabacEncodeBypassOne (pCbCtx, 0);
while (k--)
WelsCabacEncodeBypassOne (pCbCtx, (iSufS >> k) & 1);
iStopLoop = 1;
}
} while (!iStopLoop);
}
void WelsCabacEncodeFlush (SCabacCtx* pCbCtx) {
WelsCabacEncodeTerminate (pCbCtx, 1);
while (pCbCtx->m_uiBitsUsed > 0) {
if (pCbCtx->m_uiBitsUsed > 8) {
pCbCtx->m_uiBitsUsed -= 8;
uint32_t uiByte = pCbCtx->m_uData >> (pCbCtx->m_uiBitsUsed);
pCbCtx->m_uData &= (uint32_t) ((0xFFFFFFFF) >> (32 - pCbCtx->m_uiBitsUsed));
*pCbCtx->m_pBufCur ++ = uiByte;
} else {
if (pCbCtx->m_uiBitsUsed == 8) {
*pCbCtx->m_pBufCur ++ = pCbCtx->m_uData & 0xff;
} else {
*pCbCtx->m_pBufCur ++ = (pCbCtx->m_uData << (8 - pCbCtx->m_uiBitsUsed));
}
pCbCtx->m_uiBitsUsed = 0;
}
}
}
uint8_t* WelsCabacEncodeGetPtr (SCabacCtx* pCbCtx) {
return pCbCtx->m_pBufCur;
}
}

View File

@@ -38,7 +38,7 @@
*************************************************************************************
*/
#include "set_mb_syn_cavlc.h"
#include "svc_set_mb_syn.h"
#include "vlc_encoder.h"
#include "cpu_core.h"
#include "wels_const.h"
@@ -199,8 +199,47 @@ int32_t WriteBlockResidualCavlc (SWelsFuncPtrList* pFuncList, int16_t* pCoffLev
return ENC_RETURN_SUCCESS;
}
void StashMBStatusCavlc (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun) {
SBitStringAux* pBs = pSlice->pSliceBsa;
pDss->pBsStackBufPtr = pBs->pBufPtr;
pDss->uiBsStackCurBits = pBs->uiCurBits;
pDss->iBsStackLeftBits = pBs->iLeftBits;
pDss->uiLastMbQp = pSlice->uiLastMbQp;
pDss->iMbSkipRunStack = iMbSkipRun;
}
int32_t StashPopMBStatusCavlc (SDynamicSlicingStack* pDss, SSlice* pSlice) {
SBitStringAux* pBs = pSlice->pSliceBsa;
pBs->pBufPtr = pDss->pBsStackBufPtr;
pBs->uiCurBits = pDss->uiBsStackCurBits;
pBs->iLeftBits = pDss->iBsStackLeftBits;
pSlice->uiLastMbQp = pDss->uiLastMbQp;
return pDss->iMbSkipRunStack;
}
void StashMBStatusCabac (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun) {
SCabacCtx* pCtx = &pSlice->sCabacCtx;
memcpy (&pDss->sStoredCabac, pCtx, sizeof (SCabacCtx));
pDss->uiLastMbQp = pSlice->uiLastMbQp;
pDss->iMbSkipRunStack = iMbSkipRun;
}
int32_t StashPopMBStatusCabac (SDynamicSlicingStack* pDss, SSlice* pSlice) {
SCabacCtx* pCtx = &pSlice->sCabacCtx;
memcpy (pCtx, &pDss->sStoredCabac, sizeof (SCabacCtx));
pSlice->uiLastMbQp = pDss->uiLastMbQp;
return pDss->iMbSkipRunStack;
}
void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag) {
void WelsWriteSliceEndSyn (SSlice* pSlice, bool bEntropyCodingModeFlag) {
SBitStringAux* pBs = pSlice->pSliceBsa;
if (bEntropyCodingModeFlag) {
WelsCabacEncodeFlush (&pSlice->sCabacCtx);
pBs->pBufPtr = WelsCabacEncodeGetPtr (&pSlice->sCabacCtx);
} else {
BsRbspTrailingBits (pBs);
BsFlush (pBs);
}
}
void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag,int32_t iEntropyCodingModeFlag) {
pFuncList->pfCavlcParamCal = CavlcParamCal_c;
#if defined(X86_ASM)
@@ -208,6 +247,17 @@ void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag) {
// pFuncList->pfCavlcParamCal = CavlcParamCal_sse2;
}
#endif
if (iEntropyCodingModeFlag) {
pFuncList->pfStashMBStatus = StashMBStatusCabac;
pFuncList->pfStashPopMBStatus = StashPopMBStatusCabac;
pFuncList->pfWelsSpatialWriteMbSyn = WelsSpatialWriteMbSynCabac;
} else {
pFuncList->pfStashMBStatus = StashMBStatusCavlc;
pFuncList->pfStashPopMBStatus = StashPopMBStatusCavlc;
pFuncList->pfWelsSpatialWriteMbSyn = WelsSpatialWriteMbSyn;
}
}
} // namespace WelsEnc

View File

@@ -73,7 +73,7 @@ namespace WelsEnc {
void UpdateMbListNeighborParallel (SSliceCtx* pSliceCtx,
SMB* pMbList,
const int32_t uiSliceIdc) {
const uint8_t* kpMbMap = pSliceCtx->pOverallMbMap;
const uint16_t* kpMbMap = pSliceCtx->pOverallMbMap;
const int32_t kiMbWidth = pSliceCtx->iMbWidth;
int32_t iIdx = pSliceCtx->pFirstMbInSlice[uiSliceIdc];
const int32_t kiEndMbInSlice = iIdx + pSliceCtx->pCountMbNumInSlice[uiSliceIdc] - 1;
@@ -963,8 +963,11 @@ int32_t CreateSliceThreads (sWelsEncCtx* pCtx) {
int32_t iIdx = 0;
while (iIdx < kiThreadCount) {
WelsThreadCreate (&pCtx->pSliceThreading->pThreadHandles[iIdx], CodingSliceThreadProc,
&pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0);
if (WelsThreadCreate (&pCtx->pSliceThreading->pThreadHandles[iIdx], CodingSliceThreadProc,
&pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0)) {
return 1;
}
++ iIdx;
}

View File

@@ -1617,7 +1617,7 @@ bool WelsMdFirstIntraMode (void* pEnc, void* pMd, SMB* pCurMb, SMbCache* pMbCach
//chroma
pWelsMd->iCostChroma = WelsMdIntraChroma (pFunc, pEncCtx->pCurDqLayer, pMbCache, pWelsMd->iLambda);
WelsIMbChromaEncode (pEncCtx, pCurMb, pMbCache); //add pEnc&rec to MD--2010.3.15
pCurMb->uiChromPredMode = pMbCache->uiChmaI8x8Mode;
pCurMb->pSadCost[0] = 0;
return true; //intra_mb_type is best
}
@@ -1806,6 +1806,7 @@ void WelsMdIntraSecondaryModesEnc (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB*
//chroma
pWelsMd->iCostChroma = WelsMdIntraChroma (pFunc, pEncCtx->pCurDqLayer, pMbCache, pWelsMd->iLambda);
WelsIMbChromaEncode (pEncCtx, pCurMb, pMbCache); //add pEnc&rec to MD--2010.3.15
pCurMb->uiChromPredMode = pMbCache->uiChmaI8x8Mode;
pCurMb->pSadCost[0] = 0;
}

View File

@@ -78,7 +78,8 @@ int32_t AssignMbMapMultipleSlices (SSliceCtx* pSliceSeg, const SSliceConfig* kpM
const int16_t kiFirstMb = uiSliceIdx * kiMbWidth;
pSliceSeg->pCountMbNumInSlice[uiSliceIdx] = kiMbWidth;
pSliceSeg->pFirstMbInSlice[uiSliceIdx] = kiFirstMb;
memset (pSliceSeg->pOverallMbMap + kiFirstMb, (uint8_t)uiSliceIdx, kiMbWidth * sizeof (uint8_t));
WelsSetMemMultiplebytes_c(pSliceSeg->pOverallMbMap + kiFirstMb, uiSliceIdx,
kiMbWidth, sizeof(uint16_t));
++ uiSliceIdx;
}
@@ -89,7 +90,7 @@ int32_t AssignMbMapMultipleSlices (SSliceCtx* pSliceSeg, const SSliceConfig* kpM
const int32_t* kpSlicesAssignList = (int32_t*) & (kpMso->sSliceArgument.uiSliceMbNum[0]);
const int32_t kiCountNumMbInFrame = pSliceSeg->iMbNumInFrame;
const int32_t kiCountSliceNumInFrame = pSliceSeg->iSliceNumInFrame;
int32_t iSliceIdx = 0;
uint16_t iSliceIdx = 0;
int16_t iMbIdx = 0;
do {
@@ -218,9 +219,9 @@ bool CheckRasterMultiSliceSetting (const int32_t kiMbNumInFrame, SSliceArgument*
// GOM based RC related for uiSliceNum decision, only used at SM_FIXEDSLCNUM_SLICE
void GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, uint32_t* pSliceNum) {
bool GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, uint32_t* pSliceNum) {
const int32_t kiCountNumMb = kiMbWidth * kiMbHeight;
int32_t iSliceNum = *pSliceNum;
uint32_t iSliceNum = *pSliceNum;
int32_t iGomSize;
//The default RC is Bit-rate mode[Yi], but need consider as below:
@@ -236,7 +237,7 @@ void GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, u
iGomSize = kiMbWidth * GOM_ROW_MODE0_720P;
while (true) {
if (kiCountNumMb < iGomSize * iSliceNum) {
if (kiCountNumMb < iGomSize * (int32_t) iSliceNum) {
-- iSliceNum;
iSliceNum = iSliceNum - (iSliceNum & 0x01); // verfiy even num for multiple slices case
if (iSliceNum < 2) // for safe
@@ -246,15 +247,16 @@ void GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, u
break;
}
if (0 == iSliceNum)
iSliceNum = 1;
*pSliceNum = iSliceNum;
if (*pSliceNum != iSliceNum) {
*pSliceNum = (0 != iSliceNum) ? iSliceNum : 1;
return false;
}
return true;
}
// GOM based RC related for uiSliceMbNum decision, only used at SM_FIXEDSLCNUM_SLICE
void GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArg) {
bool GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArg) {
uint32_t* pSlicesAssignList = & (pSliceArg->uiSliceMbNum[0]);
const uint32_t kuiSliceNum = pSliceArg->uiSliceNum;
const int32_t kiMbNumInFrame = kiMbWidth * kiMbHeight;
@@ -292,16 +294,23 @@ void GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight,
else if (iNumMbAssigning > iMaximalMbNum)
iNumMbAssigning = iMaximalMbNum;
assert (iNumMbAssigning > 0);
if (iNumMbAssigning <= 0) {
return false;
}
iNumMbLeft -= iNumMbAssigning;
assert (iNumMbLeft > 0);
if (iNumMbLeft <= 0) {
return false;
}
pSlicesAssignList[uiSliceIdx] = iNumMbAssigning;
++ uiSliceIdx;
iMaximalMbNum = iNumMbLeft - (kuiSliceNum - uiSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts
}
pSlicesAssignList[uiSliceIdx] = iNumMbLeft;
return true;
}
@@ -384,7 +393,7 @@ int32_t InitSliceSegment (SSliceCtx* pSliceSeg,
}
if (SM_SINGLE_SLICE == uiSliceMode) {
pSliceSeg->pOverallMbMap = (uint8_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint8_t), "pSliceSeg->pOverallMbMap");
pSliceSeg->pOverallMbMap = (uint16_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint16_t), "pSliceSeg->pOverallMbMap");
WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)
pSliceSeg->iSliceNumInFrame = 1;
@@ -411,11 +420,12 @@ int32_t InitSliceSegment (SSliceCtx* pSliceSeg,
&& uiSliceMode != SM_DYN_SLICE && uiSliceMode != SM_AUTO_SLICE)
return 1;
pSliceSeg->pOverallMbMap = (uint8_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint8_t), "pSliceSeg->pOverallMbMap");
pSliceSeg->pOverallMbMap = (uint16_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint16_t), "pSliceSeg->pOverallMbMap");
WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)
memset (pSliceSeg->pOverallMbMap, 0, kiCountMbNum * sizeof (uint8_t));
WelsSetMemMultiplebytes_c(pSliceSeg->pOverallMbMap, 0, kiCountMbNum, sizeof(uint16_t));
//SM_DYN_SLICE: init, set pSliceSeg->iSliceNumInFrame = 1;
pSliceSeg->iSliceNumInFrame = GetInitialSliceNum (kiMbWidth, kiMbHeight, pMso);
@@ -542,10 +552,10 @@ void UninitSlicePEncCtx (SSliceCtx* pSliceCtx, CMemoryAlign* pMa) {
*
* \return uiSliceIdc - successful; -1 - failed;
*/
uint8_t WelsMbToSliceIdc (SSliceCtx* pSliceCtx, const int16_t kiMbXY) {
uint16_t WelsMbToSliceIdc (SSliceCtx* pSliceCtx, const int16_t kiMbXY) {
if (NULL != pSliceCtx && kiMbXY < pSliceCtx->iMbNumInFrame && kiMbXY >= 0)
return pSliceCtx->pOverallMbMap[ kiMbXY ];
return (uint8_t) (-1);
return (uint16_t) (-1);
}
/*!
@@ -680,7 +690,8 @@ int32_t DynamicAdjustSlicePEncCtxAll (SSliceCtx* pSliceCtx,
pSliceCtx->pFirstMbInSlice[iSliceIdx] = iFirstMbIdx;
pSliceCtx->pCountMbNumInSlice[iSliceIdx] = kiSliceRun;
memset (pSliceCtx->pOverallMbMap + iFirstMbIdx, (uint8_t)iSliceIdx, kiSliceRun * sizeof (uint8_t));
WelsSetMemMultiplebytes_c(pSliceCtx->pOverallMbMap + iFirstMbIdx, iSliceIdx,
kiSliceRun, sizeof(uint16_t));
iFirstMbIdx += kiSliceRun;

View File

@@ -43,7 +43,7 @@
#include "svc_enc_golomb.h"
#include "svc_base_layer_md.h"
#include "svc_encode_mb.h"
#include "svc_set_mb_syn_cavlc.h"
#include "svc_set_mb_syn.h"
#include "decode_mb_aux.h"
#include "svc_mode_decision.h"
@@ -51,7 +51,7 @@ namespace WelsEnc {
//#define ENC_TRACE
typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
typedef void (*PWelsSliceHeaderWriteFunc) (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
int32_t* pPpsIdDelta);
void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) {
@@ -237,7 +237,7 @@ void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUni
}
}
void WelsSliceHeaderWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
@@ -270,6 +270,9 @@ void WelsSliceHeaderWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSli
WriteRefPicMarking (pBs, pSliceHeader, pNalHead);
}
if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) {
BsWriteUE (pBs, pSlice->iCabacInitIdc);
}
BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */
if (pPps->bDeblockingFilterControlPresentFlag) {
@@ -288,7 +291,7 @@ void WelsSliceHeaderWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSli
BsWriteUE (pBs, 2);
break;
default :
fprintf (stderr, "pData error for deblocking");
WelsLog(&pCtx->sLogCtx, WELS_LOG_ERROR, "pData error for deblocking");
break;
}
if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) {
@@ -298,7 +301,7 @@ void WelsSliceHeaderWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSli
}
}
void WelsSliceHeaderExtWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
@@ -338,6 +341,11 @@ void WelsSliceHeaderExtWrite (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* p
}
// }
if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) {
BsWriteUE (pBs, pSlice->iCabacInitIdc);
}
BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */
if (pPps->bDeblockingFilterControlPresentFlag) {
@@ -460,21 +468,7 @@ void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSli
pfIdctFour4x4 (pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320);
}
}
inline void StashMBStatus (SDynamicSlicingStack* pDss, SBitStringAux* pBs, SSlice* pSlice, int32_t iMbSkipRun = 0) {
pDss->pBsStackBufPtr = pBs->pBufPtr;
pDss->uiBsStackCurBits = pBs->uiCurBits;
pDss->iBsStackLeftBits = pBs->iLeftBits;
pDss->uiLastMbQp = pSlice->uiLastMbQp;
pDss->iMbSkipRunStack = iMbSkipRun;
}
void StashPopMBStatus (SDynamicSlicingStack* pDss, SBitStringAux* pBs, SSlice* pSlice, int32_t* pMbSkipRun = 0) {
pBs->pBufPtr = pDss->pBsStackBufPtr;
pBs->uiCurBits = pDss->uiBsStackCurBits;
pBs->iLeftBits = pDss->iBsStackLeftBits;
pSlice->uiLastMbQp = pDss->uiLastMbQp;
if (pMbSkipRun)
*pMbSkipRun = pDss->iMbSkipRunStack;
}
void UpdateQpForOverflow (SMB* pCurMb, uint8_t kuiChromaQpIndexOffset) {
pCurMb->uiLumaQp += DELTA_QP;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
@@ -499,10 +493,12 @@ int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encodin
SWelsMD sMd;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
SBitStringAux* pBs = pSlice->pSliceBsa;
SDynamicSlicingStack sDss;
if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
WelsInitSliceCabac (pEncCtx, pSlice);
}
for (; ;) {
StashMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, 0);
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
@@ -514,9 +510,10 @@ TRY_REENCODING:
WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
UpdateNonZeroCountCache (pCurMb, pMbCache);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
StashPopMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
@@ -562,12 +559,14 @@ int32_t WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd +
SWelsMD sMd;
SDynamicSlicingStack sDss;
sDss.iStartPos = BsGetBitsPos (pBs);
if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
WelsInitSliceCabac (pEncCtx, pSlice);
}
for (; ;) {
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
StashMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, 0);
pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
// if already reaches the largest number of slices, set QPs to the upper bound
if (pSlice->bDynamicSlicingSliceSizeCtrlFlag) {
@@ -581,9 +580,9 @@ TRY_REENCODING:
WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
UpdateNonZeroCountCache (pCurMb, pMbCache);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
StashPopMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
@@ -593,7 +592,7 @@ TRY_REENCODING:
sDss.iCurrentPos = BsGetBitsPos (pBs);
if (DynSlcJudgeSliceBoundaryStepBack (pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss)) { //islice
StashPopMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx -
1; // update pLastCodedMbIdxOfPartition, need to -1 due to stepping back
++ pCurLayer->pNumSliceCodedOfPartition[kiPartitionId];
@@ -729,7 +728,7 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const
WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pBs, pCurLayer, pCurSlice,
g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
& (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0]));
#if _DEBUG
if (pEncCtx->sPSOVector.bEnableSpsPpsIdAddition) {
@@ -749,7 +748,7 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
BsRbspTrailingBits (pBs);
WelsWriteSliceEndSyn (pCurSlice, pEncCtx->pSvcParam->iEntropyCodingModeFlag != 0);
return ENC_RETURN_SUCCESS;
}
@@ -777,7 +776,7 @@ void UpdateMbNeighbourInfoForNextSlice (SSliceCtx* pSliceCtx,
bool bLeftTop;
bool bRightTop;
int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
const uint8_t kuiSliceIdc = WelsMbToSliceIdc (pSliceCtx, kiMbXY);
const uint16_t kuiSliceIdc = WelsMbToSliceIdc (pSliceCtx, kiMbXY);
pMb->uiSliceIdc = kuiSliceIdc;
iLeftXY = kiMbXY - 1;
@@ -815,9 +814,9 @@ void AddSliceBoundary (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, SSliceCtx* pSlic
int32_t iFirstMbIdxOfNextSlice, const int32_t kiLastMbIdxInPartition) {
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
int32_t iCurMbIdx = pCurMb->iMbXY;
int32_t iCurSliceIdc = pSliceCtx->pOverallMbMap[ iCurMbIdx ];
uint16_t iCurSliceIdc = pSliceCtx->pOverallMbMap[ iCurMbIdx ];
const int32_t kiSliceIdxStep = pEncCtx->iActiveThreadsNum;
int32_t iNextSliceIdc = iCurSliceIdc + kiSliceIdxStep;
uint16_t iNextSliceIdc = iCurSliceIdc + kiSliceIdxStep;
SSlice* pNextSlice = NULL;
SMB* pMbList = pCurLayer->sMbDataP;
@@ -840,9 +839,8 @@ void AddSliceBoundary (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, SSliceCtx* pSlic
sizeof (SSliceHeaderExt)); // confirmed_safe_unsafe_usage
pSliceCtx->pFirstMbInSlice[iNextSliceIdc] = iFirstMbIdxOfNextSlice;
memset (pSliceCtx->pOverallMbMap + iFirstMbIdxOfNextSlice, (uint8_t)iNextSliceIdc,
(kiLastMbIdxInPartition - iFirstMbIdxOfNextSlice + 1)*sizeof (uint8_t));
WelsSetMemMultiplebytes_c (pSliceCtx->pOverallMbMap + iFirstMbIdxOfNextSlice, iNextSliceIdc,
(kiLastMbIdxInPartition - iFirstMbIdxOfNextSlice + 1), sizeof(uint16_t));
//DYNAMIC_SLICING_ONE_THREAD: update pMbList slice_neighbor_info
UpdateMbNeighbourInfoForNextSlice (pSliceCtx, pMbList, iFirstMbIdxOfNextSlice, kiLastMbIdxInPartition);
@@ -876,6 +874,10 @@ bool DynSlcJudgeSliceBoundaryStepBack (void* pCtx, void* pSlice, SSliceCtx* pSli
&& JUMPPACKETSIZE_JUDGE (uiLen, iCurMbIdx, pSliceCtx->uiSliceSizeConstraint)) /*jump_avoiding_pack_exceed*/
&& kbCurMbNotLastMbOfCurPartition) { //decide to add new pSlice
WelsLog (&pEncCtx->sLogCtx, WELS_LOG_DETAIL,
"DynSlcJudgeSliceBoundaryStepBack: AddSliceBoundary: iCurMbIdx=%d, uiLen=%d, uiSliceIdx=%d", iCurMbIdx, uiLen,
pCurSlice->uiSliceIdx);
if (pEncCtx->pSvcParam->iMultipleThreadIdc > 1) {
WelsMutexLock (&pEncCtx->pSliceThreading->mutexSliceNumUpdate);
//lock the acessing to this variable: pSliceCtx->iSliceNumInFrame
@@ -942,7 +944,6 @@ int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
int32_t iNumMbCoded = 0;
int32_t iNextMbIdx = kiSliceFirstMbXY;
int32_t iCurMbIdx = -1;
int32_t iMbSkipRun = 0;
const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;
uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];
@@ -950,8 +951,12 @@ int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
SDynamicSlicingStack sDss;
if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
WelsInitSliceCabac (pEncCtx, pSlice);
}
pSlice->iMbSkipRun = 0;
for (;;) {
StashMBStatus (&sDss, pBs, pSlice, iMbSkipRun);
pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);
//point to current pMb
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
@@ -979,23 +984,16 @@ TRY_REENCODING:
UpdateNonZeroCountCache (pCurMb, pMbCache);
//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
if (IS_SKIP (pCurMb->uiMbType)) {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
iMbSkipRun++;
} else {
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
StashPopMBStatus (&sDss, pBs, pSlice, &iMbSkipRun);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
//step (7): reconstruct current MB
pCurMb->uiSliceIdc = kiSliceIdx;
@@ -1017,8 +1015,8 @@ TRY_REENCODING:
}
}
if (iMbSkipRun) {
BsWriteUE (pBs, iMbSkipRun);
if (pSlice->iMbSkipRun) {
BsWriteUE (pBs, pSlice->iMbSkipRun);
}
return iEncReturn;
@@ -1038,7 +1036,6 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
int32_t iNextMbIdx = kiSliceFirstMbXY;
int32_t iCurMbIdx = -1;
int32_t iMbSkipRun = 0;
const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;
uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
@@ -1048,10 +1045,14 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
SDynamicSlicingStack sDss;
sDss.iStartPos = BsGetBitsPos (pBs);
if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
WelsInitSliceCabac (pEncCtx, pSlice);
}
pSlice->iMbSkipRun = 0;
for (;;) {
//DYNAMIC_SLICING_ONE_THREAD - MultiD
//stack pBs pointer
StashMBStatus (&sDss, pBs, pSlice, iMbSkipRun);
pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);
//point to current pMb
iCurMbIdx = iNextMbIdx;
@@ -1088,28 +1089,22 @@ TRY_REENCODING:
//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
if (IS_SKIP (pCurMb->uiMbType)) {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
iMbSkipRun++;
} else {
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
StashPopMBStatus (&sDss, pBs, pSlice, &iMbSkipRun);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
goto TRY_REENCODING;
}
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
//DYNAMIC_SLICING_ONE_THREAD - MultiD
sDss.iCurrentPos = BsGetBitsPos (pBs);
if (DynSlcJudgeSliceBoundaryStepBack (pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss)) {
StashPopMBStatus (&sDss, pBs, pSlice, &iMbSkipRun);
pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx -
1; // update pLastCodedMbIdxOfPartition, need to -1 due to stepping back
++ pCurLayer->pNumSliceCodedOfPartition[kiPartitionId];
@@ -1139,8 +1134,8 @@ TRY_REENCODING:
}
}
if (iMbSkipRun) {
BsWriteUE (pBs, iMbSkipRun);
if (pSlice->iMbSkipRun) {
BsWriteUE (pBs, pSlice->iMbSkipRun);
}
return iEncReturn;

View File

@@ -718,7 +718,7 @@ int32_t RequestScreenBlockFeatureStorage (CMemoryAlign* pMa, const int32_t kiFra
pScreenBlockFeatureStorage->iIs16x16 = !bIsBlock8x8;
pScreenBlockFeatureStorage->uiFeatureStrategyIndex = kiFeatureStrategyIndex;
pScreenBlockFeatureStorage->iActualListSize = kiListSize;
memset (pScreenBlockFeatureStorage->uiSadCostThreshold, UINT_MAX, BLOCK_SIZE_ALL * sizeof (uint32_t));
WelsSetMemMultiplebytes_c (pScreenBlockFeatureStorage->uiSadCostThreshold, UINT_MAX, BLOCK_SIZE_ALL, sizeof(uint32_t));
pScreenBlockFeatureStorage->bRefBlockFeatureCalculated = false;
return ENC_RETURN_SUCCESS;

View File

@@ -0,0 +1,693 @@
/*!
* \copy
* Copyright (c) 2009-2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* \file svc_set_mb_syn_cabac.cpp
*
* \brief wrtie cabac syntax
*
* \date 9/28/2014 Created
*
*************************************************************************************
*/
#include "svc_set_mb_syn.h"
#include "set_mb_syn_cabac.h"
#include "svc_enc_golomb.h"
namespace WelsEnc {
static const uint16_t uiSignificantCoeffFlagOffset[5] = {0, 15, 29, 44, 47};
static const uint16_t uiLastCoeffFlagOffset[5] = {0, 15, 29, 44, 47};
static const uint16_t uiCoeffAbsLevelMinus1Offset[5] = {0, 10, 20, 30, 39};
static const uint16_t uiCodecBlockFlagOffset[5] = {0, 4, 8, 12, 16};
static void WelsCabacMbType (SCabacCtx* pCabacCtx, SMB* pCurMb, SMbCache* pMbCache, int32_t iMbWidth,
EWelsSliceType eSliceType) {
if (eSliceType == I_SLICE) {
uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
SMB* pLeftMb = pCurMb - 1 ;
SMB* pTopMb = pCurMb - iMbWidth;
int32_t iCtx = 3;
if ((uiNeighborAvail & LEFT_MB_POS) && !IS_INTRA4x4 (pLeftMb->uiMbType))
iCtx++;
if ((uiNeighborAvail & TOP_MB_POS) && !IS_INTRA4x4 (pTopMb->uiMbType)) //TOP MB
iCtx++;
if (pCurMb->uiMbType == MB_TYPE_INTRA4x4) {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 0);
} else {
int32_t iCbpChroma = pCurMb->uiCbp >> 4;
int32_t iCbpLuma = pCurMb->uiCbp & 15;
int32_t iPredMode = g_kiMapModeI16x16[pMbCache->uiLumaI16x16Mode];
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
WelsCabacEncodeTerminate (pCabacCtx, 0);
if (iCbpLuma)
WelsCabacEncodeDecision (pCabacCtx, 6, 1);
else
WelsCabacEncodeDecision (pCabacCtx, 6, 0);
if (iCbpChroma == 0)
WelsCabacEncodeDecision (pCabacCtx, 7, 0);
else {
WelsCabacEncodeDecision (pCabacCtx, 7, 1);
WelsCabacEncodeDecision (pCabacCtx, 8, iCbpChroma >> 1);
}
WelsCabacEncodeDecision (pCabacCtx, 9, iPredMode >> 1);
WelsCabacEncodeDecision (pCabacCtx, 10, iPredMode & 1);
}
} else if (eSliceType == P_SLICE) {
uint32_t uiMbType = pCurMb->uiMbType;
if (uiMbType == MB_TYPE_16x16) {
WelsCabacEncodeDecision (pCabacCtx, 14, 0);
WelsCabacEncodeDecision (pCabacCtx, 15, 0);
WelsCabacEncodeDecision (pCabacCtx, 16, 0);
} else if ((uiMbType == MB_TYPE_16x8) || (uiMbType == MB_TYPE_8x16)) {
WelsCabacEncodeDecision (pCabacCtx, 14, 0);
WelsCabacEncodeDecision (pCabacCtx, 15, 1);
WelsCabacEncodeDecision (pCabacCtx, 17, pCurMb->uiMbType == MB_TYPE_16x8);
} else if ((uiMbType == MB_TYPE_8x8) || (uiMbType == MB_TYPE_8x8_REF0)) {
WelsCabacEncodeDecision (pCabacCtx, 14, 0);
WelsCabacEncodeDecision (pCabacCtx, 15, 0);
WelsCabacEncodeDecision (pCabacCtx, 16, 1);
} else if (pCurMb->uiMbType == MB_TYPE_INTRA4x4) {
WelsCabacEncodeDecision (pCabacCtx, 14, 1);
WelsCabacEncodeDecision (pCabacCtx, 17, 0);
} else {
int32_t iCbpChroma = pCurMb->uiCbp >> 4;
int32_t iCbpLuma = pCurMb->uiCbp & 15;
int32_t iPredMode = g_kiMapModeI16x16[pMbCache->uiLumaI16x16Mode];
//prefix
WelsCabacEncodeDecision (pCabacCtx, 14, 1);
//suffix
WelsCabacEncodeDecision (pCabacCtx, 17, 1);
WelsCabacEncodeTerminate (pCabacCtx, 0);
if (iCbpLuma)
WelsCabacEncodeDecision (pCabacCtx, 18, 1);
else
WelsCabacEncodeDecision (pCabacCtx, 18, 0);
if (iCbpChroma == 0)
WelsCabacEncodeDecision (pCabacCtx, 19, 0);
else {
WelsCabacEncodeDecision (pCabacCtx, 19, 1);
WelsCabacEncodeDecision (pCabacCtx, 19, iCbpChroma >> 1);
}
WelsCabacEncodeDecision (pCabacCtx, 20, iPredMode >> 1);
WelsCabacEncodeDecision (pCabacCtx, 20, iPredMode & 1);
}
}
}
void WelsCabacMbIntra4x4PredMode (SCabacCtx* pCabacCtx, SMbCache* pMbCache) {
for (int32_t iMode = 0; iMode < 16; iMode++) {
bool bPredFlag = pMbCache->pPrevIntra4x4PredModeFlag[iMode];
int8_t iRemMode = pMbCache->pRemIntra4x4PredModeFlag[iMode];
if (bPredFlag)
WelsCabacEncodeDecision (pCabacCtx, 68, 1);
else {
WelsCabacEncodeDecision (pCabacCtx, 68, 0);
WelsCabacEncodeDecision (pCabacCtx, 69, iRemMode & 0x01);
WelsCabacEncodeDecision (pCabacCtx, 69, (iRemMode >> 1) & 0x01);
WelsCabacEncodeDecision (pCabacCtx, 69, (iRemMode >> 2));
}
}
}
void WelsCabacMbIntraChromaPredMode (SCabacCtx* pCabacCtx, SMB* pCurMb, SMbCache* pMbCache, int32_t iMbWidth) {
uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
SMB* pLeftMb = pCurMb - 1 ;
SMB* pTopMb = pCurMb - iMbWidth;
int32_t iPredMode = g_kiMapModeIntraChroma[pMbCache->uiChmaI8x8Mode];
int32_t iCtx = 64;
if ((uiNeighborAvail & LEFT_MB_POS) && g_kiMapModeIntraChroma[pLeftMb->uiChromPredMode] != 0)
iCtx++;
if ((uiNeighborAvail & TOP_MB_POS) && g_kiMapModeIntraChroma[pTopMb->uiChromPredMode] != 0)
iCtx++;
if (iPredMode == 0) {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 0);
} else if (iPredMode == 1) {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
WelsCabacEncodeDecision (pCabacCtx, 67, 0);
} else if (iPredMode == 2) {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
WelsCabacEncodeDecision (pCabacCtx, 67, 1);
WelsCabacEncodeDecision (pCabacCtx, 67, 0);
} else {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
WelsCabacEncodeDecision (pCabacCtx, 67, 1);
WelsCabacEncodeDecision (pCabacCtx, 67, 1);
}
}
void WelsCabacMbCbp (SMB* pCurMb, int32_t iMbWidth, SCabacCtx* pCabacCtx) {
int32_t iCbpBlockLuma[4] = { (pCurMb->uiCbp) & 1, (pCurMb->uiCbp >> 1) & 1, (pCurMb->uiCbp >> 2) & 1, (pCurMb->uiCbp >> 3) & 1};
int32_t iCbpChroma = pCurMb->uiCbp >> 4;
int32_t iCbpBlockLeft[4] = {0, 0, 0, 0};
int32_t iCbpBlockTop[4] = {0, 0, 0, 0};
int32_t iCbpLeftChroma = 0;
int32_t iCbpTopChroma = 0;
int32_t iCbp = 0;
int32_t iCtx = 0;
uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
if (uiNeighborAvail & LEFT_MB_POS) {
iCbp = (pCurMb - 1)->uiCbp;
iCbpBlockLeft[0] = ! (iCbp & 1);
iCbpBlockLeft[1] = ! ((iCbp >> 1) & 1);
iCbpBlockLeft[2] = ! ((iCbp >> 2) & 1);
iCbpBlockLeft[3] = ! ((iCbp >> 3) & 1);
iCbpLeftChroma = iCbp >> 4;
if (iCbpLeftChroma)
iCtx += 1;
}
if (uiNeighborAvail & TOP_MB_POS) {
iCbp = (pCurMb - iMbWidth)->uiCbp;
iCbpBlockTop[0] = ! (iCbp & 1);
iCbpBlockTop[1] = ! ((iCbp >> 1) & 1);
iCbpBlockTop[2] = ! ((iCbp >> 2) & 1);
iCbpBlockTop[3] = ! ((iCbp >> 3) & 1);
iCbpTopChroma = iCbp >> 4;
if (iCbpTopChroma)
iCtx += 2;
}
WelsCabacEncodeDecision (pCabacCtx, 73 + iCbpBlockLeft[1] + iCbpBlockTop[2] * 2, iCbpBlockLuma[0]);
WelsCabacEncodeDecision (pCabacCtx, 73 + !iCbpBlockLuma[0] + iCbpBlockTop[3] * 2, iCbpBlockLuma[1]);
WelsCabacEncodeDecision (pCabacCtx, 73 + iCbpBlockLeft[3] + (!iCbpBlockLuma[0]) * 2 , iCbpBlockLuma[2]);
WelsCabacEncodeDecision (pCabacCtx, 73 + !iCbpBlockLuma[2] + (!iCbpBlockLuma[1]) * 2, iCbpBlockLuma[3]);
//chroma
if (iCbpChroma) {
WelsCabacEncodeDecision (pCabacCtx, 77 + iCtx, 1);
WelsCabacEncodeDecision (pCabacCtx, 81 + (iCbpLeftChroma >> 1) + ((iCbpTopChroma >> 1) * 2), iCbpChroma > 1);
} else {
WelsCabacEncodeDecision (pCabacCtx, 77 + iCtx, 0);
}
}
void WelsCabacMbDeltaQp (SMB* pCurMb, SCabacCtx* pCabacCtx, bool bFirstMbInSlice) {
SMB* pPrevMb = NULL;
int32_t iCtx = 0;
if (!bFirstMbInSlice) {
pPrevMb = pCurMb - 1;
pCurMb->iLumaDQp = pCurMb->uiLumaQp - pPrevMb->uiLumaQp;
if (IS_SKIP (pPrevMb->uiMbType) || ((pPrevMb->uiMbType != MB_TYPE_INTRA16x16) && (!pPrevMb->uiCbp))
|| (!pPrevMb->iLumaDQp))
iCtx = 0;
else
iCtx = 1;
}
if (pCurMb->iLumaDQp) {
int32_t iValue = pCurMb->iLumaDQp < 0 ? (-2 * pCurMb->iLumaDQp) : (2 * pCurMb->iLumaDQp - 1);
WelsCabacEncodeDecision (pCabacCtx, 60 + iCtx, 1);
if (iValue == 1) {
WelsCabacEncodeDecision (pCabacCtx, 60 + 2, 0);
} else {
WelsCabacEncodeDecision (pCabacCtx, 60 + 2, 1);
iValue--;
while ((--iValue) > 0)
WelsCabacEncodeDecision (pCabacCtx, 60 + 3, 1);
WelsCabacEncodeDecision (pCabacCtx, 60 + 3, 0);
}
} else {
WelsCabacEncodeDecision (pCabacCtx, 60 + iCtx, 0);
}
}
void WelsMbSkipCabac (SCabacCtx* pCabacCtx, SMB* pCurMb, int32_t iMbWidth, EWelsSliceType eSliceType,
int16_t bSkipFlag) {
int32_t iCtx = (eSliceType == P_SLICE) ? 11 : 24;
uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
if (uiNeighborAvail & LEFT_MB_POS) { //LEFT MB
if (!IS_SKIP ((pCurMb - 1)->uiMbType))
iCtx++;
}
if (uiNeighborAvail & TOP_MB_POS) { //TOP MB
if (!IS_SKIP ((pCurMb - iMbWidth)->uiMbType))
iCtx++;
}
WelsCabacEncodeDecision (pCabacCtx, iCtx, bSkipFlag);
if (bSkipFlag) {
for (int i = 0; i < 4; i++) {
pCurMb->sMvd[i].iMvX = 0;
pCurMb->sMvd[i].iMvY = 0;
}
pCurMb->uiCbp = pCurMb->iCbpDc = 0;
}
}
void WelsCabacMbRef (SCabacCtx* pCabacCtx, SMB* pCurMb, SMbCache* pMbCache, int16_t iIdx) {
SMVComponentUnit* pMvComp = &pMbCache->sMvComponents;
const int16_t iRefIdxA = pMvComp->iRefIndexCache[iIdx + 6];
const int16_t iRefIdxB = pMvComp->iRefIndexCache[iIdx + 1];
int16_t iRefIdx = pMvComp->iRefIndexCache[iIdx + 7];
int16_t iCtx = 0;
if ((iRefIdxA > 0) && (!pMbCache->bMbTypeSkip[3]))
iCtx++;
if ((iRefIdxB > 0) && (!pMbCache->bMbTypeSkip[1]))
iCtx += 2;
while (iRefIdx > 0) {
WelsCabacEncodeDecision (pCabacCtx, 54 + iCtx, 1);
iCtx = (iCtx >> 2) + 4;
iRefIdx--;
}
WelsCabacEncodeDecision (pCabacCtx, 54 + iCtx, 0);
}
inline void WelsCabacMbMvdLx (SCabacCtx* pCabacCtx, int32_t sMvd, int32_t iCtx, int32_t iPredMvd) {
const int32_t iAbsMvd = WELS_ABS (sMvd);
int32_t iCtxInc = 0;
int32_t iPrefix = WELS_MIN (iAbsMvd, 9);
int32_t i = 0;
if (iPredMvd > 32)
iCtxInc += 2;
else if (iPredMvd > 2)
iCtxInc += 1;
if (iPrefix) {
if (iPrefix < 9) {
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 1);
iCtxInc = 3;
for (i = 0; i < iPrefix - 1; i++) {
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 1);
if (i < 3)
iCtxInc++;
}
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 0);
WelsCabacEncodeBypassOne (pCabacCtx, sMvd < 0);
} else {
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 1);
iCtxInc = 3;
for (i = 0; i < (9 - 1); i++) {
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 1);
if (i < 3)
iCtxInc++;
}
WelsCabacEncodeUeBypass (pCabacCtx, 3, iAbsMvd - 9);
WelsCabacEncodeBypassOne (pCabacCtx, sMvd < 0);
}
} else {
WelsCabacEncodeDecision (pCabacCtx, iCtx + iCtxInc, 0);
}
}
SMVUnitXY WelsCabacMbMvd (SCabacCtx* pCabacCtx, SMB* pCurMb, uint32_t iMbWidth,
SMVUnitXY sCurMv, SMVUnitXY sPredMv, int16_t iBlockIdx) {
uint32_t iAbsMvd0, iAbsMvd1;
uint8_t uiNeighborAvail = pCurMb->uiNeighborAvail;
SMVUnitXY sMvd;
SMVUnitXY sMvdLeft;
SMVUnitXY sMvdTop;
sMvdLeft.iMvX = sMvdLeft.iMvY = sMvdTop.iMvX = sMvdTop.iMvY = 0;
sMvd.sDeltaMv (sCurMv, sPredMv);
if (((iBlockIdx == 0) || (iBlockIdx == 1)) && (uiNeighborAvail & TOP_MB_POS)) {
sMvdTop.sAssginMv ((pCurMb - iMbWidth)->sMvd[iBlockIdx + 2]);
}
if ((iBlockIdx == 2) || (iBlockIdx == 3)) {
sMvdTop.sAssginMv (pCurMb->sMvd[iBlockIdx - 2]);
}
if (((iBlockIdx == 0) || (iBlockIdx == 2)) && (uiNeighborAvail & LEFT_MB_POS)) {
sMvdLeft.sAssginMv ((pCurMb - 1)->sMvd[iBlockIdx + 1]);
}
if ((iBlockIdx == 1) || (iBlockIdx == 3)) {
sMvdLeft.sAssginMv (pCurMb->sMvd[iBlockIdx - 1]);
}
iAbsMvd0 = WELS_ABS (sMvdLeft.iMvX) + WELS_ABS (sMvdTop.iMvX);
iAbsMvd1 = WELS_ABS (sMvdLeft.iMvY) + WELS_ABS (sMvdTop.iMvY);
WelsCabacMbMvdLx (pCabacCtx, sMvd.iMvX, 40, iAbsMvd0);
WelsCabacMbMvdLx (pCabacCtx, sMvd.iMvY, 47, iAbsMvd1);
return sMvd;
}
int16_t WelsGetMbCtxCabac (SMbCache* pMbCache, SMB* pCurMb, uint32_t iMbWidth, ECtxBlockCat eCtxBlockCat,
int16_t iIdx) {
int16_t iNzA = -1, iNzB = -1;
int8_t* pNonZeroCoeffCount = pMbCache->iNonZeroCoeffCount;
int32_t bIntra = IS_INTRA (pCurMb->uiMbType);
int32_t iCtxInc = 0;
switch (eCtxBlockCat) {
case LUMA_AC:
case CHROMA_AC:
case LUMA_4x4:
iNzA = pNonZeroCoeffCount[iIdx - 1];
iNzB = pNonZeroCoeffCount[iIdx - 8];
break;
case LUMA_DC:
case CHROMA_DC:
if (pCurMb->uiNeighborAvail & LEFT_MB_POS)
iNzA = (pCurMb - 1)->iCbpDc & (1 << iIdx);
if (pCurMb->uiNeighborAvail & TOP_MB_POS)
iNzB = (pCurMb - iMbWidth)->iCbpDc & (1 << iIdx);
break;
default:
break;
}
if (((iNzA == -1) && bIntra) || (iNzA > 0))
iCtxInc += 1;
if (((iNzB == -1) && bIntra) || (iNzB > 0))
iCtxInc += 2;
return 85 + uiCodecBlockFlagOffset[eCtxBlockCat] + iCtxInc;
}
void WelsWriteBlockResidualCabac (SMbCache* pMbCache, SMB* pCurMb, uint32_t iMbWidth, SCabacCtx* pCabacCtx,
ECtxBlockCat eCtxBlockCat, int16_t iIdx, int16_t iNonZeroCount, int16_t* pBlock, int16_t iEndIdx) {
int32_t iCtx = WelsGetMbCtxCabac (pMbCache, pCurMb, iMbWidth, eCtxBlockCat, iIdx);
if (iNonZeroCount) {
ENFORCE_STACK_ALIGN_1D (int16_t, iAbsLevel, 16, 16);
ENFORCE_STACK_ALIGN_1D (int16_t, iSignLevel, 16, 16);
const int32_t iCtxSig = 105 + uiSignificantCoeffFlagOffset[eCtxBlockCat];
const int32_t iCtxLast = 166 + uiLastCoeffFlagOffset[eCtxBlockCat];
const int32_t iCtxLevel = 227 + uiCoeffAbsLevelMinus1Offset[eCtxBlockCat];
int32_t iNonZeroIdx = 0;
int32_t i = 0;
int32_t iNumAbsLevelEq1 = 0;
int32_t iNumAbsLevelGt1 = 0;
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
while (1) {
if (pBlock[i]) {
iSignLevel[iNonZeroIdx] = pBlock[i] < 0;
iAbsLevel[iNonZeroIdx] = WELS_ABS (pBlock[i]) - 1;
iNonZeroIdx++;
WelsCabacEncodeDecision (pCabacCtx, iCtxSig + i, 1);
if (iNonZeroIdx != iNonZeroCount)
WelsCabacEncodeDecision (pCabacCtx, iCtxLast + i, 0);
else {
WelsCabacEncodeDecision (pCabacCtx, iCtxLast + i, 1);
break;
}
} else
WelsCabacEncodeDecision (pCabacCtx, iCtxSig + i, 0);
i++;
if (i == iEndIdx) {
iSignLevel[iNonZeroIdx] = pBlock[i] < 0;
iAbsLevel[iNonZeroIdx] = WELS_ABS (pBlock[i]) - 1;
iNonZeroIdx++;
break;
}
}
do {
int32_t iPrefix = 0;
iNonZeroIdx--;
iPrefix = WELS_MIN (iAbsLevel[iNonZeroIdx], 14);
if (iPrefix) {
iCtx = iCtxLevel + ((iNumAbsLevelGt1 != 0) ? 0 : WELS_MIN (4, 1 + iNumAbsLevelEq1));
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
iCtx = iCtxLevel + 5 + WELS_MIN (4 - (eCtxBlockCat == CHROMA_DC), iNumAbsLevelGt1);
for (i = 0; i < iPrefix - 1; i++)
WelsCabacEncodeDecision (pCabacCtx, iCtx, 1);
if (iPrefix < 14)
WelsCabacEncodeDecision (pCabacCtx, iCtx, 0);
else
WelsCabacEncodeUeBypass (pCabacCtx, 0, iAbsLevel[iNonZeroIdx] - 14);
iNumAbsLevelGt1++;
} else {
iCtx = iCtxLevel + ((iNumAbsLevelGt1 != 0) ? 0 : WELS_MIN (4, 1 + iNumAbsLevelEq1));
WelsCabacEncodeDecision (pCabacCtx, iCtx, 0);
iNumAbsLevelEq1++;
}
WelsCabacEncodeBypassOne (pCabacCtx, iSignLevel[iNonZeroIdx]);
} while (iNonZeroIdx > 0);
} else {
WelsCabacEncodeDecision (pCabacCtx, iCtx, 0);
}
}
int32_t WelsCalNonZeroCount (int16_t* pBlock, int16_t iNum) {
int32_t iCount = 0;
for (int16_t i = 0; i < iNum; i++) {
if (pBlock[i])
iCount++;
}
return iCount;
}
int32_t WelsWriteMbResidualCabac (SSlice* pSlice, SMbCache* sMbCacheInfo, SMB* pCurMb, SCabacCtx* pCabacCtx,
int16_t iMbWidth, uint32_t uiChromaQpIndexOffset) {
const uint16_t uiMbType = pCurMb->uiMbType;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
int16_t i = 0;
int8_t* pNonZeroCoeffCount = pMbCache->iNonZeroCoeffCount;
SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
const int32_t iSliceFirstMbXY = pSliceHeadExt->sSliceHeader.iFirstMbInSlice;
pCurMb->iCbpDc = 0;
pCurMb->iLumaDQp = 0;
if ((pCurMb->uiCbp > 0) || (uiMbType == MB_TYPE_INTRA16x16)) {
int32_t iCbpChroma = pCurMb->uiCbp >> 4;
int32_t iCbpLuma = pCurMb->uiCbp & 15;
pCurMb->iLumaDQp = pCurMb->uiLumaQp - pSlice->uiLastMbQp;
WelsCabacMbDeltaQp (pCurMb, pCabacCtx, (pCurMb->iMbXY == iSliceFirstMbXY));
pSlice->uiLastMbQp = pCurMb->uiLumaQp;
if (uiMbType == MB_TYPE_INTRA16x16) {
//Luma DC
int iNonZeroCount = WelsCalNonZeroCount (pMbCache->pDct->iLumaI16x16Dc, 16);
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, LUMA_DC, 0, iNonZeroCount,
pMbCache->pDct->iLumaI16x16Dc, 15);
if (iNonZeroCount)
pCurMb->iCbpDc |= 1;
//Luma AC
if (iCbpLuma) {
for (i = 0; i < 16; i++) {
int32_t iIdx = g_kuiCache48CountScan4Idx[i];
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, LUMA_AC, iIdx,
pNonZeroCoeffCount[iIdx], pMbCache->pDct->iLumaBlock[i], 14);
}
}
} else {
//Luma AC
for (i = 0; i < 16; i++) {
if (iCbpLuma & (1 << (i >> 2))) {
int32_t iIdx = g_kuiCache48CountScan4Idx[i];
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, LUMA_4x4, iIdx,
pNonZeroCoeffCount[iIdx], pMbCache->pDct->iLumaBlock[i], 15);
}
}
}
if (iCbpChroma) {
int32_t iNonZeroCount = 0;
//chroma DC
iNonZeroCount = WelsCalNonZeroCount (pMbCache->pDct->iChromaDc[0], 4);
if (iNonZeroCount)
pCurMb->iCbpDc |= 0x2;
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, CHROMA_DC, 1, iNonZeroCount,
pMbCache->pDct->iChromaDc[0], 3);
iNonZeroCount = WelsCalNonZeroCount (pMbCache->pDct->iChromaDc[1], 4);
if (iNonZeroCount)
pCurMb->iCbpDc |= 0x4;
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, CHROMA_DC, 2, iNonZeroCount,
pMbCache->pDct->iChromaDc[1], 3);
if (iCbpChroma & 0x02) {
const uint8_t* g_kuiCache48CountScan4Idx_16base = &g_kuiCache48CountScan4Idx[16];
//Cb AC
for (i = 0; i < 4; i++) {
int32_t iIdx = g_kuiCache48CountScan4Idx_16base[i];
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, CHROMA_AC, iIdx,
pNonZeroCoeffCount[iIdx], pMbCache->pDct->iChromaBlock[i], 14);
}
//Cr AC
for (i = 0; i < 4; i++) {
int32_t iIdx = 24 + g_kuiCache48CountScan4Idx_16base[i];
WelsWriteBlockResidualCabac (pMbCache, pCurMb, iMbWidth, pCabacCtx, CHROMA_AC, iIdx,
pNonZeroCoeffCount[iIdx], pMbCache->pDct->iChromaBlock[4 + i], 14);
}
}
}
} else {
pCurMb->iLumaDQp = 0;
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + uiChromaQpIndexOffset)];
}
return 0;
}
void WelsInitSliceCabac (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
/* alignment needed */
SBitStringAux* pBs = pSlice->pSliceBsa;
BsAlign (pBs);
/* init cabac */
WelsCabacContextInit (pEncCtx, &pSlice->sCabacCtx, pSlice->iCabacInitIdc);
WelsCabacEncodeInit (&pSlice->sCabacCtx, pBs->pBufPtr, pBs->pBufEnd);
}
int32_t WelsSpatialWriteMbSynCabac (void* pCtx, SSlice* pSlice, SMB* pCurMb) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
SCabacCtx* pCabacCtx = &pSlice->sCabacCtx;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
const uint16_t uiMbType = pCurMb->uiMbType;
SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
uint32_t uiNumRefIdxL0Active = pSliceHeadExt->sSliceHeader.uiNumRefIdxL0Active - 1;
const int32_t iSliceFirstMbXY = pSliceHeadExt->sSliceHeader.iFirstMbInSlice;
int16_t i = 0;
int16_t iMbWidth = pEncCtx->pCurDqLayer->iMbWidth;
uint32_t uiChromaQpIndexOffset = pEncCtx->pCurDqLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
SMVUnitXY sMvd;
int32_t iRet = 0;
if (pCurMb->iMbXY > iSliceFirstMbXY)
WelsCabacEncodeTerminate (&pSlice->sCabacCtx, 0);
if (IS_SKIP (pCurMb->uiMbType)) {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + uiChromaQpIndexOffset)];
WelsMbSkipCabac (&pSlice->sCabacCtx, pCurMb, iMbWidth, pEncCtx->eSliceType, 1);
} else {
//skip flag
if (pEncCtx->eSliceType != I_SLICE)
WelsMbSkipCabac (&pSlice->sCabacCtx, pCurMb, iMbWidth, pEncCtx->eSliceType, 0);
//write mb type
WelsCabacMbType (pCabacCtx, pCurMb, pMbCache, iMbWidth, pEncCtx->eSliceType);
if (IS_INTRA (uiMbType)) {
if (uiMbType == MB_TYPE_INTRA4x4) {
WelsCabacMbIntra4x4PredMode (pCabacCtx, pMbCache);
}
WelsCabacMbIntraChromaPredMode (pCabacCtx, pCurMb, pMbCache, iMbWidth);
sMvd.iMvX = sMvd.iMvY = 0;
pCurMb->sMvd[0].sAssginMv (sMvd);
pCurMb->sMvd[1].sAssginMv (sMvd);
pCurMb->sMvd[2].sAssginMv (sMvd);
pCurMb->sMvd[3].sAssginMv (sMvd);
} else if (uiMbType == MB_TYPE_16x16) {
if (uiNumRefIdxL0Active > 0) {
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 0);
}
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[0], pMbCache->sMbMvp[0], 0);
pCurMb->sMvd[0].sAssginMv (sMvd);
pCurMb->sMvd[1].sAssginMv (sMvd);
pCurMb->sMvd[2].sAssginMv (sMvd);
pCurMb->sMvd[3].sAssginMv (sMvd);
} else if (uiMbType == MB_TYPE_16x8) {
if (uiNumRefIdxL0Active > 0) {
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 0);
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 12);
}
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth , pCurMb->sMv[0], pMbCache->sMbMvp[0], 0);
pCurMb->sMvd[0].sAssginMv (sMvd);
pCurMb->sMvd[1].sAssginMv (sMvd);
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[8], pMbCache->sMbMvp[1], 2);
pCurMb->sMvd[2].sAssginMv (sMvd);
pCurMb->sMvd[3].sAssginMv (sMvd);
} else if (uiMbType == MB_TYPE_8x16) {
if (uiNumRefIdxL0Active > 0) {
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 0);
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 2);
}
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[0], pMbCache->sMbMvp[0], 0);
pCurMb->sMvd[0].sAssginMv (sMvd);
pCurMb->sMvd[2].sAssginMv (sMvd);
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[2], pMbCache->sMbMvp[1], 1);
pCurMb->sMvd[1].sAssginMv (sMvd);
pCurMb->sMvd[3].sAssginMv (sMvd);
} else if ((uiMbType == MB_TYPE_8x8) || (uiMbType == MB_TYPE_8x8_REF0)) {
for (i = 0; i < 4; i++)
WelsCabacEncodeDecision (pCabacCtx, 21, 1);
if (uiNumRefIdxL0Active > 0) {
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 0);
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 2);
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 12);
WelsCabacMbRef (pCabacCtx, pCurMb, pMbCache, 14);
}
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[0], pMbCache->sMbMvp[0], 0);
pCurMb->sMvd[0].sAssginMv (sMvd);
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[2], pMbCache->sMbMvp[1], 1);
pCurMb->sMvd[1].sAssginMv (sMvd);
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[8], pMbCache->sMbMvp[2], 2);
pCurMb->sMvd[2].sAssginMv (sMvd);
sMvd = WelsCabacMbMvd (pCabacCtx, pCurMb, iMbWidth, pCurMb->sMv[10], pMbCache->sMbMvp[3], 3);
pCurMb->sMvd[3].sAssginMv (sMvd);
}
if (uiMbType != MB_TYPE_INTRA16x16) {
WelsCabacMbCbp (pCurMb, iMbWidth, pCabacCtx);
}
iRet = WelsWriteMbResidualCabac (pSlice, pMbCache, pCurMb, pCabacCtx, iMbWidth, uiChromaQpIndexOffset);
}
if (!IS_INTRA (pCurMb->uiMbType))
pCurMb->uiChromPredMode = 0;
return iRet;
}
}

View File

@@ -40,7 +40,7 @@
#include "vlc_encoder.h"
#include "ls_defines.h"
#include "svc_set_mb_syn_cavlc.h"
#include "svc_set_mb_syn.h"
namespace WelsEnc {
const uint32_t g_kuiIntra4x4CbpMap[48] = {
@@ -220,40 +220,54 @@ int32_t CheckBitstreamBuffer (const uint32_t kuiSliceIdx, sWelsEncCtx* pEncCtx,
}
//============================Base Layer CAVLC Writing===============================
int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
int32_t WelsSpatialWriteMbSyn (void* pCtx, SSlice* pSlice, SMB* pCurMb) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
SBitStringAux* pBs = pSlice->pSliceBsa;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
const uint8_t kuiChromaQpIndexOffset = pEncCtx->pCurDqLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
/* Step 1: write mb type and pred */
if (IS_Inter_8x8 (pCurMb->uiMbType)) {
WelsSpatialWriteSubMbPred (pEncCtx, pSlice, pCurMb);
if (IS_SKIP (pCurMb->uiMbType)) {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
pSlice->iMbSkipRun++;
return ENC_RETURN_SUCCESS;
} else {
WelsSpatialWriteMbPred (pEncCtx, pSlice, pCurMb);
if (pEncCtx->eSliceType != I_SLICE) {
BsWriteUE (pBs, pSlice->iMbSkipRun);
pSlice->iMbSkipRun = 0;
}
/* Step 1: write mb type and pred */
if (IS_Inter_8x8 (pCurMb->uiMbType)) {
WelsSpatialWriteSubMbPred (pEncCtx, pSlice, pCurMb);
} else {
WelsSpatialWriteMbPred (pEncCtx, pSlice, pCurMb);
}
/* Step 2: write coded block patern */
if (IS_INTRA4x4 (pCurMb->uiMbType)) {
BsWriteUE (pBs, g_kuiIntra4x4CbpMap[pCurMb->uiCbp]);
} else if (!IS_INTRA16x16 (pCurMb->uiMbType)) {
BsWriteUE (pBs, g_kuiInterCbpMap[pCurMb->uiCbp]);
}
/* Step 3: write QP and residual */
if (pCurMb->uiCbp > 0 || IS_INTRA16x16 (pCurMb->uiMbType)) {
const int32_t kiDeltaQp = pCurMb->uiLumaQp - pSlice->uiLastMbQp;
pSlice->uiLastMbQp = pCurMb->uiLumaQp;
BsWriteSE (pBs, kiDeltaQp);
if (WelsWriteMbResidual (pEncCtx->pFuncList, pMbCache, pCurMb, pBs))
return ENC_RETURN_VLCOVERFLOWFOUND;
} else {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp +
pEncCtx->pCurDqLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset)];
}
/* Step 4: Check the left buffer */
return CheckBitstreamBuffer (pSlice->uiSliceIdx, pEncCtx, pBs);
}
/* Step 2: write coded block patern */
if (IS_INTRA4x4 (pCurMb->uiMbType)) {
BsWriteUE (pBs, g_kuiIntra4x4CbpMap[pCurMb->uiCbp]);
} else if (!IS_INTRA16x16 (pCurMb->uiMbType)) {
BsWriteUE (pBs, g_kuiInterCbpMap[pCurMb->uiCbp]);
}
/* Step 3: write QP and residual */
if (pCurMb->uiCbp > 0 || IS_INTRA16x16 (pCurMb->uiMbType)) {
const int32_t kiDeltaQp = pCurMb->uiLumaQp - pSlice->uiLastMbQp;
pSlice->uiLastMbQp = pCurMb->uiLumaQp;
BsWriteSE (pBs, kiDeltaQp);
if (WelsWriteMbResidual (pEncCtx->pFuncList, pMbCache, pCurMb, pBs))
return ENC_RETURN_VLCOVERFLOWFOUND;
} else {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp +
pEncCtx->pCurDqLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset)];
}
/* Step 4: Check the left buffer */
return CheckBitstreamBuffer (pSlice->uiSliceIdx, pEncCtx, pBs);
}
int32_t WelsWriteMbResidual (SWelsFuncPtrList* pFuncList, SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs) {

View File

@@ -219,7 +219,8 @@ int32_t CWelsPreProcess::AnalyzeSpatialPic (sWelsEncCtx* pCtx, const int32_t kiD
if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (m_pEncCtx->pVaa);
SRefInfoParam* BestRefCandidateParam = & (pVaaExt->sVaaStrBestRefCandidate[0]);
SRefInfoParam* BestRefCandidateParam = (pCtx->bCurFrameMarkedAsSceneLtr) ? (& (pVaaExt->sVaaLtrBestRefCandidate[0])) :
(& (pVaaExt->sVaaStrBestRefCandidate[0]));
SPicture* pRefPic = m_pSpatialPic[0][BestRefCandidateParam->iSrcListIdx];
VaaCalculation (pCtx->pVaa, pCurPic, pRefPic, false, bCalculateVar, bCalculateBGD);
@@ -1116,21 +1117,21 @@ ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPi
pVaaExt->iVaaBestRefFrameNum = sLtrSaved.pRefPicture->iFrameNum;
pVaaExt->pVaaBestBlockStaticIdc = sLtrSaved.pBestBlockStaticIdc;
if (0 == iAvailableSceneRefNum) {
SaveBestRefToVaa (sSceneLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[1]));
if (0 < iAvailableSceneRefNum) {
SaveBestRefToVaa (sSceneLtrSaved, & (pVaaExt->sVaaLtrBestRefCandidate[0]));
}
pVaaExt->iNumOfAvailableRef = 1;
return static_cast<ESceneChangeIdc> (iVaaFrameSceneChangeIdc);
}
int32_t CWelsPreProcess::GetRefFrameInfo (int32_t iRefIdx, SPicture*& pRefOri) {
int32_t CWelsPreProcess::GetRefFrameInfo (int32_t iRefIdx, bool bCurrentFrameIsSceneLtr, SPicture*& pRefOri) {
const int32_t iTargetDid = m_pEncCtx->pSvcParam->iSpatialLayerNum - 1;
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (m_pEncCtx->pVaa);
SRefInfoParam* BestRefCandidateParam = & (pVaaExt->sVaaStrBestRefCandidate[iRefIdx]);
int32_t iLtrRefIdx = m_pSpatialPic[iTargetDid][BestRefCandidateParam->iSrcListIdx]->iLongTermPicNum;
pRefOri = m_pSpatialPic[iTargetDid][BestRefCandidateParam->iSrcListIdx];
return iLtrRefIdx;
SRefInfoParam* pBestRefCandidateParam = (bCurrentFrameIsSceneLtr) ? (& (pVaaExt->sVaaLtrBestRefCandidate[iRefIdx])) :
(& (pVaaExt->sVaaStrBestRefCandidate[iRefIdx]));
pRefOri = m_pSpatialPic[iTargetDid][pBestRefCandidateParam->iSrcListIdx];
return (m_pSpatialPic[iTargetDid][pBestRefCandidateParam->iSrcListIdx]->iLongTermPicNum);
}
void CWelsPreProcess::Padding (uint8_t* pSrcY, uint8_t* pSrcU, uint8_t* pSrcV, int32_t iStrideY, int32_t iStrideUV,
int32_t iActualWidth, int32_t iPaddingWidth, int32_t iActualHeight, int32_t iPaddingHeight) {

View File

@@ -102,7 +102,7 @@ class CWelsH264SVCEncoder : public ISVCEncoder {
void CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc);
void CheckReferenceNumSetting (int32_t iNumRef);
void TraceParamInfo(SEncParamExt *pParam);
void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, const int64_t kiCurrentFrameMs);
void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs);
sWelsEncCtx* m_pEncContext;

View File

@@ -431,7 +431,7 @@ int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture* pSrcPic, S
return cmUnkonwReason;
}
UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, kiCurrentFrameMs);
UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, pBsInfo->iFrameSizeInBytes, kiCurrentFrameMs);
///////////////////for test
#ifdef OUTPUT_BIT_STREAM
@@ -504,6 +504,8 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) {
ForceCodingIDR (m_pEncContext);
m_pEncContext->sEncoderStatistics.uiIDRReqNum++;
return 0;
}
void CWelsH264SVCEncoder::CheckProfileSetting (int32_t iLayer, EProfileIdc uiProfileIdc) {
@@ -594,7 +596,7 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
}
void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType,
const int64_t kiCurrentFrameMs) {
const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs) {
SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics);
int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1;
@@ -616,9 +618,11 @@ void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVid
pStatistics->uiSkippedFrameCount += (kbCurrentFrameSkipped ? 1 : 0);
// rate control related
if (0 != m_pEncContext->uiStartTimestamp && kiCurrentFrameTs > m_pEncContext->uiStartTimestamp + 800) {
pStatistics->fAverageFrameRate = pStatistics->uiInputFrameCount * 1000 /
(kiCurrentFrameTs - m_pEncContext->uiStartTimestamp);
if (0 != m_pEncContext->uiStartTimestamp) {
if (kiCurrentFrameTs > m_pEncContext->uiStartTimestamp + 800) {
pStatistics->fAverageFrameRate = (static_cast<float> (pStatistics->uiInputFrameCount) * 1000 /
(kiCurrentFrameTs - m_pEncContext->uiStartTimestamp));
}
} else {
m_pEncContext->uiStartTimestamp = kiCurrentFrameTs;
}
@@ -631,20 +635,35 @@ void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVid
if (m_pEncContext->pLtr->bLTRMarkingFlag) {
pStatistics->uiLTRSentNum ++;
}
//TODO: update uiIDRReqNum in forceIDR
m_pEncContext->iTotalEncodedBits += kiCurrentFrameSize;
if (m_pEncContext->iStatisticsLogInterval > 0) {
if (WELS_ABS (kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs) > m_pEncContext->iStatisticsLogInterval) {
int64_t iTimeDiff = kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs;
if ((iTimeDiff > m_pEncContext->iStatisticsLogInterval) || (0 == pStatistics->uiInputFrameCount % 300)) {
if (iTimeDiff) {
pStatistics->fLatestFrameRate = static_cast<float> ((pStatistics->uiInputFrameCount - m_pEncContext->iLastStatisticsFrameCount) * 1000 /
iTimeDiff);
pStatistics->uiBitRate = static_cast<unsigned int> ((m_pEncContext->iTotalEncodedBits -
m_pEncContext->iLastStatisticsBits) * 1000 / iTimeDiff);
}
// update variables
m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs;
m_pEncContext->iLastStatisticsBits = m_pEncContext->iTotalEncodedBits;
m_pEncContext->iLastStatisticsFrameCount = pStatistics->uiInputFrameCount;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"EncoderStatistics: %dx%d, SpeedInMs: %f, AverFrameRate=%f, LastFrameRate=NA, LatestBitRate=NA, uiInputFrameCount=%d, uiSkippedFrameCount=%d, uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA",
"EncoderStatistics: %dx%d, SpeedInMs: %f, fAverageFrameRate=%f, \
LastFrameRate=%f, LatestBitRate=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, \
uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA",
pStatistics->uiWidth, pStatistics->uiHeight,
pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate,
pStatistics->fLatestFrameRate, pStatistics->uiBitRate,
pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount,
pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRSentNum, pStatistics->uiLTRSentNum);
pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum);
//TODO: the following statistics will be calculated and added later
//pStatistics->fLatestFrameRate, pStatistics->uiBitRate,
//pStatistics->uiIDRReqNum,
m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs;
//pStatistics->uiLTRSentNum
}
}
@@ -771,6 +790,9 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
//adjust to valid range
m_pEncContext->pSvcParam->fMaxFrameRate = WELS_CLIP3 (iValue, MIN_FRAME_RATE, MAX_FRAME_RATE);
WelsEncoderApplyFrameRate (m_pEncContext->pSvcParam);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_FRAME_RATE,m_pEncContext->pSvcParam->fMaxFrameRate= %f",
m_pEncContext->pSvcParam->fMaxFrameRate);
}
break;
case ENCODER_OPTION_BITRATE: { // Target bit-rate
@@ -812,7 +834,16 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
break;
}
//adjust to valid range
WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
return cmInitParaError;
} else {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
}
}
break;
case ENCODER_OPTION_MAX_BITRATE: { // Target bit-rate
@@ -855,17 +886,31 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
break;
}
//adjust to valid range
WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
return cmInitParaError;
} else {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
}
}
break;
case ENCODER_OPTION_RC_MODE: { // 0:quality mode;1:bit-rate mode;2:bitrate limited mode
int32_t iValue = * ((int32_t*)pOption);
m_pEncContext->pSvcParam->iRCMode = (RC_MODES) iValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_RC_MODE iRCMode= %d ",
iValue);
}
break;
case ENCODER_PADDING_PADDING: { // 0:disable padding;1:padding
int32_t iValue = * ((int32_t*)pOption);
m_pEncContext->pSvcParam->iPaddingFlag = iValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_PADDING_PADDING iPaddingFlag= %d ",
iValue);
}
break;
case ENCODER_LTR_RECOVERY_REQUEST: {
@@ -881,6 +926,9 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
case ENCODER_LTR_MARKING_PERIOD: {
uint32_t iValue = * ((uint32_t*) (pOption));
m_pEncContext->pSvcParam->iLtrMarkPeriod = iValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_LTR_MARKING_PERIOD iLtrMarkPeriod= %d ",
iValue);
}
break;
case ENCODER_OPTION_LTR: {
@@ -888,6 +936,10 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
if (WelsEncoderApplyLTR (&m_pWelsTrace->m_sLogCtx, &m_pEncContext, pLTRValue)) {
return cmInitParaError;
}
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_LTR,expected bEnableLongTermReference = %d,expeced iLTRRefNum = %d,actual bEnableLongTermReference = %d,actual iLTRRefNum = %d",
pLTRValue->bEnableLongTermReference, pLTRValue->iLTRRefNum, m_pEncContext->pSvcParam->bEnableLongTermReference,
m_pEncContext->pSvcParam->iLTRRefNum);
}
break;
case ENCODER_OPTION_ENABLE_SSEI: {
@@ -960,6 +1012,10 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
return cmInitParaError;
}
CheckProfileSetting (pProfileInfo->iLayer, pProfileInfo->uiProfileIdc);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_PROFILE,layerId = %d,expected profile = %d,actual profile = %d",
pProfileInfo->iLayer, pProfileInfo->uiProfileIdc,
m_pEncContext->pSvcParam->sSpatialLayers[pProfileInfo->iLayer].uiProfileIdc);
}
break;
case ENCODER_OPTION_LEVEL: {
@@ -970,21 +1026,31 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
return cmInitParaError;
}
CheckLevelSetting (pLevelInfo->iLayer, pLevelInfo->uiLevelIdc);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_LEVEL,layerId = %d,expected level = %d,actual level = %d",
pLevelInfo->iLayer, pLevelInfo->uiLevelIdc, m_pEncContext->pSvcParam->sSpatialLayers[pLevelInfo->iLayer].uiLevelIdc);
}
break;
case ENCODER_OPTION_NUMBER_REF: {
int32_t iValue = * ((int32_t*)pOption);
CheckReferenceNumSetting (iValue);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_NUMBER_REF,expected refNum = %d,actual refnum = %d", iValue,
m_pEncContext->pSvcParam->iNumRefFrame);
}
break;
case ENCODER_OPTION_DELIVERY_STATUS: {
SDeliveryStatus* pValue = (static_cast<SDeliveryStatus*> (pOption));
m_pEncContext->bDeliveryFlag = pValue->bDeliveryFlag;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DELIVERY_STATUS,bDeliveryFlag = %d", pValue->bDeliveryFlag);
}
break;
case ENCODER_OPTION_COMPLEXITY: {
int32_t iValue = * (static_cast<int32_t*> (pOption));
m_pEncContext->pSvcParam->iComplexityMode = (ECOMPLEXITY_MODE)iValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_COMPLEXITY,iComplexityMode = %d", iValue);
}
break;
case ENCODER_OPTION_GET_STATISTICS: {
@@ -995,11 +1061,15 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
case ENCODER_OPTION_STATISTICS_LOG_INTERVAL: {
int32_t iValue = * (static_cast<int32_t*> (pOption));
m_pEncContext->iStatisticsLogInterval = iValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_STATISTICS_LOG_INTERVAL,iStatisticsLogInterval = %d", iValue);
}
break;
case ENCODER_OPTION_IS_LOSSLESS_LINK: {
bool bValue = * (static_cast<bool*> (pOption));
m_pEncContext->pSvcParam->bIsLosslessLink = bValue;
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_IS_LOSSLESS_LINK,bIsLosslessLink = %d", bValue);
}
break;
default:

View File

@@ -18,6 +18,7 @@ ENCODER_CPP_SRCS=\
$(ENCODER_SRCDIR)/core/src/ratectl.cpp\
$(ENCODER_SRCDIR)/core/src/ref_list_mgr_svc.cpp\
$(ENCODER_SRCDIR)/core/src/sample.cpp\
$(ENCODER_SRCDIR)/core/src/set_mb_syn_cabac.cpp\
$(ENCODER_SRCDIR)/core/src/set_mb_syn_cavlc.cpp\
$(ENCODER_SRCDIR)/core/src/slice_multi_threading.cpp\
$(ENCODER_SRCDIR)/core/src/svc_base_layer_md.cpp\
@@ -26,6 +27,7 @@ ENCODER_CPP_SRCS=\
$(ENCODER_SRCDIR)/core/src/svc_encode_slice.cpp\
$(ENCODER_SRCDIR)/core/src/svc_mode_decision.cpp\
$(ENCODER_SRCDIR)/core/src/svc_motion_estimate.cpp\
$(ENCODER_SRCDIR)/core/src/svc_set_mb_syn_cabac.cpp\
$(ENCODER_SRCDIR)/core/src/svc_set_mb_syn_cavlc.cpp\
$(ENCODER_SRCDIR)/core/src/wels_preprocess.cpp\
$(ENCODER_SRCDIR)/plus/src/welsEncoderExt.cpp\

View File

@@ -340,7 +340,6 @@ void CBackgroundDetection::ForegroundDilationAndBackgroundErosion (vBGDParam* pB
int8_t* pVaaBackgroundMbFlag = (int8_t*)pBgdParam->pBackgroundMbFlag;
SBackgroundOU* pOUNeighbours[4];//0: left; 1: right; 2: top; 3: bottom
pBackgroundOU = pBgdParam->pOU_array;
pOUNeighbours[2] = pBackgroundOU;//top OU
for (int32_t j = 0; j < iPicHeightInOU; j ++) {
int8_t* pRowSkipFlag = pVaaBackgroundMbFlag;

View File

@@ -91,9 +91,7 @@ CVpFrameWork::CVpFrameWork (uint32_t uiThreadsNum, EResult& eReturn) {
uint32_t uiCPUFlag = WelsCPUFeatureDetect (&iCoreNum);
for (int32_t i = 0; i < MAX_STRATEGY_NUM; i++) {
IStrategy* pStrategy = m_pStgChain[i];
pStrategy = CreateStrategy (WelsStaticCast (EMethods, i + 1), uiCPUFlag);
m_pStgChain[i] = pStrategy;
m_pStgChain[i] = CreateStrategy (WelsStaticCast (EMethods, i + 1), uiCPUFlag);
}
WelsMutexInit (&m_mutes);

1865
docs/doxygen/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

25
docs/doxygen/Home.rest Normal file
View File

@@ -0,0 +1,25 @@
.. contents::
:local:
1. Overview
---------------------
<doxygen2rst page=Overview> Overview </doxygen2rst>
2. Page index
---------------------
- `ISVCEncoder <wiki/ISVCEncoder>`_
- `ISVCDecoder <wiki/ISVCDecoder>`_
- `Example code for encoder usage <wiki/UsageExampleForEncoder>`_
- `Example code for decoder usage <wiki/UsageExampleForDecoder>`_
- `How to update wiki page <wiki/API2Wiki>`_
3. Classes
---------------------
- `ISVCEncoder <wiki/ISVCEncoder>`_
- `ISVCDecoder <wiki/ISVCDecoder>`_
- `Types and Structures <wiki/TypesAndStructures>`_
4. License
---------------------
<doxygen2rst page=License> License </doxygen2rst>

View File

@@ -0,0 +1,19 @@
This file describes the interface of ISVCDecoder
.. contents::
:local:
:depth: 2
Methods(ISVCDecoder)
============================
<doxygen2rst class=ISVCDecoder> Class:ISVCDecoder </doxygen2rst>
Global functions
============================
<doxygen2rst function=WelsGetDecoderCapability> function:WelsGetDecoderCapability </doxygen2rst>
<doxygen2rst function=WelsCreateDecoder> function:WelsCreateDecoder </doxygen2rst>
<doxygen2rst function=WelsDestroyDecoder> function:WelsDestroyDecoder </doxygen2rst>

View File

@@ -0,0 +1,16 @@
This file describes the interface of ISVCEncoder
.. contents::
:local:
:depth: 2
Methods(ISVCEncoder)
============================
<doxygen2rst class=ISVCEncoder> Class:ISVCEncoder </doxygen2rst>
Global functions
===========================
<doxygen2rst function=WelsCreateSVCEncoder> function:WelsCreateSVCEncoder </doxygen2rst>
<doxygen2rst function=WelsDestroySVCEncoder> function:WelsDestroySVCEncoder </doxygen2rst>

View File

@@ -0,0 +1,10 @@
This page is about the example of decoder usage
.. contents::
:local:
:depth: 2
Decoder Usage Example(ISVCDecoder)
=================================
<doxygen2rst page=DecoderUsageExample> Decoder usage example </doxygen2rst>

View File

@@ -0,0 +1,15 @@
This page is about the example of encoder usage
.. contents::
:local:
:depth: 2
Encoder Usage Example-1
============================
<doxygen2rst page=EncoderUsageExample1> Encoder usage example 1 </doxygen2rst>
Encoder Usage Example-2
============================
<doxygen2rst page=EncoderUsageExample2> Encoder usage example 2 </doxygen2rst>

Some files were not shown because too many files have changed in this diff Show More