This will be necessary for an efficient and straightforward
implementation of hor_sad for blocks over 16 pixels wide, because they
cannot use the shuffle trick because inter-lane shuffling is so hard to
do
NOTE: To force generic SAD implementation on devices supporting
vectorized variants, you now have to override both get_optimized_sad
and reg_sad to generic (only overriding get_optimized_sad on AVX2
hardware would just run all SAD blocks through reg_sad_avx2). Let's
see if there's a more sensible way to do it, but it's not trivial.
Avoid mm_set1 operation when it's possible to create the constant with
one bit-shift operation from another instead. Thanks Intel for
3-operand instruction encoding!
AVX2 support on a processor should always imply BMI and ABM support.
The lzcnt and tzcnt instructions have more suitable semantics in the
corner case that source word is 0, and allow us to even handle that
scenario without a branch. Apparently Visual Studio will already
include this support when building with AVX2 enabled, so only the
automake files need to be tweaked.
Adds command line option --fast-residual-cost=<limit>. When QP is below
the limit, estimates the cost of coding the residual coefficients from
the sum of absolute coefficients. Skipping CABAC is not worth it with
high QPs because there are fewer coefficients so CABAC is not as slow.
PowerPC target may lack or have non-standard FPU:
$ cc -dumpmachine
powerpcspe-undermydesk-freebsd
$ cc -c -maltivec -Isrc src/strategies/altivec/picture-altivec.c
src/strategies/altivec/picture-altivec.c:1: error: AltiVec and E500 instructions cannot coexist
All intra coding is a special case so it can be permitted even though
Kvazaar normally only supports intra periods that are divisible by the
GOP length.
- Replaces lcu_dqp_enabled with max_qp_delta_depth in encoder_control_t.
- Fixes set_cu_qps so that it can handle quantization groups of
arbitrary size.
- Fixes computation of QP predictors so that it works for quantization
groups of arbitrary size.
Changes asserts on the reference count of objects to assert the value
after KVZ_ATOMIC_INC instead of directly checking the value. Fixes some
data races detected by TSan.
- Adds missing default values.
- Adds help for --crypto and --key.
- Adds help for --rd=3.
- Adds help for --sao options.
- Some changes to help wording.
The transform skip flag in cu_info_t was stored under the intra
substruct even though transform skip can be used for inter as well. This
caused bitstream errors. Fixed by moving the flag out of the substruct.
Adds an additional grid search step that starts from the zero motion
vector after the normal grid search. The search range for this step is
half of the normal range.
- Changes TZ grid search and star refinement to keep the origin constant
instead of moving to the best position after each iteration.
- Changes star refinement to loop until there is no more improvement,
instead of running the step only once.
When the starting point for integer motion estimation was selected among
the merge candidates, the candidate motion vectors were always rounded
down. This commit changes the rounding so that they are rounded to the
nearest integer MV instead.
Changes reference index list creation so that the negative references
are added to L1 in addition to L0 when biprediction is enabled and no
reordering of pictures is done. Biprediction can now be used with the
low-delay GOP structure.
Changes the crypto module to use unsigned char instead of byte. The byte
typedef is no longer included in the global namespace in crypto++ 6.0.0.
See https://github.com/weidai11/cryptopp/issues/442.
Fixes#184.
Checks the cost of flushing all coefficients of an inter block to zero.
This is much faster than doing full RDOQ but can still reduce bitrate
significantly. Encoding speed is increased since fewer coefficient bits
have to be coded with CABAC.
Moves duplicate code for writing the MVD of a single motion vector from
kvz_get_mvd_coding_cost_cabac and encoder_inter_prediction_unit to a new
function.
SMP/AMP search is performed using a lower work tree level than the
normal inter search so the prediction info must be copied up if an
SMP/AMP mode is chosen. Previously pixels and coefficient were copied as
well. Changed to only copy prediction info.
DST function was returned for inter luma transform blocks of size 4x4
even though they must use DCT. Fixed by checking the prediction mode of
the block in addition to whether it is chroma or luma.
When 4x4 intra blocks are enabled and inter search is limited to 16x16
and larger blocks, it is possible that inter search is accidentally done
for 4x4 blocks. Fixed by checking that block size is at least 8x8 before
doing inter search.
Overrides the linkers used for kvazaar, libkvazaar.la and kvazaar_tests.
When crypto++ is enabled, the C++ linker is used and when it is
disabled, the C linker is used.
This removes the need to explicitly specify -lstdc++ in configure when
crypto++ is used and fixes the build with crypto++ when libstd++ is not
installed.
- Fixes two errors in calculating the POC for the reference frame for
temporal candidate MV scaling.
- Fixes using the MV for the wrong direction when the temporal MV
predictor block uses bi-prediction.
Fixes#160.
Changes handling of intra pictures for --gop=8 so that every picture
with POC divisible by the intra period is intra. The first picture is
IDR and the rest of the intra pictures are CRA. POC is not reset at CRA
pictures. The leading pictures that follow the CRA picture are changed
to RASL so they are allowed to refer to pictures before the CRA picture.
Changes inter slice types to P when the L1 reference list is empty and
to B otherwise.
In all-intra, all pictures are now IDR pictures with POC zero.
When using --gop=8 with an intra period greater than one, a single POC
would be skipped before every intra frame. This commit fixes the problem
by turning the intra frames into BLA frames with leading pictures when
using --gop=8.
Changes thread queue so that only the jobs that are ready to run are
stored in the queue. Other jobs are kept track of by pointers in the
reverse dependency lists of other jobs. When a job is ready to run it is
appended to the queue. The job queue is stored as a linked list.
The definitions of threadqueue_queue_t and threadqueue_job_t are moved
to the .c file, turning them into opaque structs.
Makes thread queue code simpler. Fixes some TSan errors.
Adds struct inter_search_info_t for holding the parameters that are used
by most function related to inter search. Passing the parameters in
a single struct greatly reduces the number of parameters for many
functions.
Functions kvz_sao_reconstruct and encoder_sao_reconstruct used
frame->width as the stride instead of frame->rec->stride when accessing
frame->rec->data. This caused errors when using tiles and SAO.
Changes the work_tree parameter in search.c functions from an array to
a pointer. Fixes "formal parameter with requested alignment of 8 won't
be aligned" errors.
Changes field state->tile->frame->cu_array->data to point to the CU
array in the main encoder state. Removes the need to copy the CU array
to the main CU array after search.
Inter costs are computed using SAD except when fractional motion
estimation or bi-prediction is enabled. This commit changes
search_pu_inter_ref to recalculate the cost with SATD. Fixes inter/intra
cost comparisons since intra costs are always SATD costs.
Changes function kvz_get_coeff_cost to only copy the CABAC contexts and
not the whole encoder state.
Other threads could be simultaneously using the other parts of the
encoder state. Only copying the CABAC fixes a TSan data race warning.
Adds alignment attribute to lcu_coeff_t. The coefficients are sometimes
handled as 64-bit integers containing four coefficients so the arrays
should be aligned to 8 bytes.
Fixes a UBSan error about misaligned reads.
Changes OWF selection so that it is chosen based on the maximum number
of parallel CTUs. Number of threads is limited to prevent overhead from
extra threads.
Drop pthread_cond_broadcast on threadqueue->cond in function
kvz_threadqueue_waitfor. The broadcast caused threads to be woken up
more often than necessary.
Changes encoder_state_init_new_frame to only call normalize_lcu_weights
when the weights have been written to the array and rate control is
enabled. When rate control is disabled, the weights are not used.
Adds field max_inter_ref_lcu to encoder_control_t. It is used to set up
inter-LCU dependencies in encoder_state_encode_leaf and restrict motion
vectors in fracmv_within_tile.
When using WPP and OWF, the first CTU of a row depends on the last CTU
of the row below in the reference frame. This is necessary when SAO is
enabled since we currently do SAO for a whole CTU row at a time. When
SAO is disabled, however, it is unnecessary to wait for the whole row.
Changes CTUs to depend only on the CTU below in the reference frame
instead of the whole row when WPP and OWF are enabled and SAO disabled.
Gives a significant speedup when running on a machine with many CPU
cores.
Moves SAO reconstruction into encoder_state_worker_encode_lcu instead of
doing it in a separate step for the whole CTU row. Reconstruction of the
rightmost 10 pixels and bottommost 10 pixels of a CTU is delayed until
the neighboring CTU has been deblocked.
Doing SAO for the whole CTU row at a time caused unnecessary inter-CTU
dependencies when using WPP and OWF. The first CTU of a row would need
to wait until SAO was done for the row below in the previous frame.
Moving SAO reconstruction to immediately after deblocking each CTU fixes
this problem.
Adds width and height parameters to function kvz_sao_reconstruct and
changes it to take coordinates in units of pixels. This will be useful
for doing SAO for areas smaller than a whole CTU.
AVX2 filter functions read pixels in chunks of 8 or 16 bytes. At the end
of the block, the read goes out of the bounds of the pixels array. The
extra pixels do not affect the result.
Fixes valgrind complaining about the invalid reads by allocating 5 extra
pixels in kvz_get_extended_block_avx2
With low delay GOP structure, it is possible to use an intra period that
is not a multiple of the GOP structure length. Commit 00c9f52 changed
encoder_state_init_new_frame to reset POC on intra frames. GOP offset,
however, was not reset, resulting in invalid POCs and references for the
following frames.
This commit changes function kvz_encoder_feed_frame so that GOP offset
is correctly reset on intra frames.
When closing the encoder, the pictures stored in the input frame buffer
are freed by repeatedly calling kvz_encoder_feed_frame. If the encoder
was closed immediately after opening it, kvz_encoder_feed_frame would be
called with an unprepared encoder state. This would trigger an assert.
Fixed by changing kvz_encoder_feed_frame so that it does not require the
encoder state to be prepared.
Sets max_transform_hierarchy_depth_inter to 0 in SPS. This saves some
bits because split_transform_flag does not need to be coded for inter
blocks.
When SMP and AMP blocks are enabled the depth is set to 1 instead.
Otherwise inter split flag would default to 1 for SMP and AMP blocks,
resulting in an unnecessary transform split.
Changes kvazaar_close to stop all threads before freeing encoder states.
Fixes a crash when the encoder is closed before all pictures have been
encoded.
Changes kvazaar_close to free the remaining pictures in the the input
frame buffer. Fixes a memory leak when the encoder is closed while there
are pictures left in the buffer.
Replaces function kvz_intra_recon_lcu_luma and
kvz_intra_recon_lcu_chroma in intra.c with function kvz_intra_recon_cu.
The new function can handle reconstruction for both luma and chroma.
Removes some duplicated code.
Moves code for intra leaf transform block reconstruction from functions
kvz_intra_recon_lcu_luma and kvz_intra_recon_lcu_chroma to a new
function intra_recon_tb_leaf. Removes some duplicated code.
Changes functions encode_intra_coding_unit and encode_coding_tree to
take coordinate arguments in units of luma pixels instead of 8 px
blocks. This should make the code easier to understand.
Changes functions encode_transform_unit and encode_transform_coeff to
take coordinate arguments in units of luma pixels instead of 4 px
blocks. This should make the code easier to understand.
When kvazaar was built with crypto++ but running without using
encryption features, kvazaar attempted to delete an uninitialized crypto
handle. Fixed by setting the handle to NULL in kvz_encoder_state_init.
A CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption was allocated at the
beginning of encoder_state_encode_leaf and was never freed. This commit
changes encoder_state_worker_encode_lcu to delete the CFB_Mode. Also
moves crypto handle from encoder_state_config_tile_t to encoder_state_t
so that it can be safely deleted without affecting other threads in the
same tile.
Moves the inline declaration of intra_mode_encryption before the type
and changes it to use the INLINE macro. Inline declaration after type
triggered a warning on GCC.
Fixes the order of acquiring locks for the job and its dependency in
kvz_threadqueue_job_dep_add. The dependency is locked before the job
that depends on it. This is the same order as in threadqueue_worker.
Acquiring the locks in different order in kvz_threadqueue_job_dep_add
and threadqueue_worker would sometimes result in a deadlock.
When using --me-early-termination=sensitive, early termination of inter
search used to always return the starting point if no tested motion
vector was good enough to continue the search. This commit changes
early_termination to always return the best motion vector and cost
found.
Changes kvz_config_validate to output an error if the given QP is out of
range and changes kvz_set_picture_lambda_and_qp to clip the QP to the
valid range if is too large after applying QP offset from GOP structure.
Replaces functions kvz_quantize_lcu_luma_residual and
kvz_quantize_lcu_chroma_residual in transform.c with function
kvz_quantize_lcu_residual. The new function can handle any of the YUV
colors. Removes some duplicated code.
Changes the way coefficients are passed from kvz_search_lcu to
kvz_encode_coding_tree. Drops fields coeff_y, coeff_u and coeff_v in
videoframe_t and instead passes them through field coeff in
endoder_state_t.
Adds option --erp-aqp for enabling adaptive QP for 360 degree video with
equirectangular projection. When projected into a spherical surface,
the middle part of the video covers relatively larger area than the top
and bottom parts. Enabling --erp-aqp sets up a ROI delta QP array which
uses higher QPs for the top and bottom of the video and lower QPs for
the middle part.
Delta QPs for LCUs are enabled when either ROI coding or rate control is
enabled. Having a single field is simpler than always checking whether
ROI or rate control is enabled.
When video width or height was not a multiple of the smallest CU size,
no prediction would be performed at the border CUs. Kvazaar would later
crash at an assertion failure when attempting to write the bitstream for
the CU.
Fixed by permitting inter and intra prediction when the CU split is
forced, even if CUs of that size would otherwise be disabled.
When WPP is enabled, a reference to SAO reconstruction job is copied
from the wavefront to the main encoder state. However, when threads are
disabled, the job is a null pointer and dereferencing it crashes the
encoder. Fixed by adding a null pointer check.
Both the thread queue and the encoder states hold pointers to the thread
queue jobs. It is possible that a job is removed from the thread queue
and freed while the encoder state is still using it. This commit adds
reference counting to threadqueue_job_t in order to fix the problem.
Fixes#161.
Pthread mutexes were used for synchronization in encmain by locking and
unlocking them from different threads. However, according to the POSIX
standard, unlocking a mutex from a different thread is undefined
behaviour. This commit replaces the mutexes by semaphores which can be
used from different threads.
Following warning was given and is false positive
error: 'memset' used with length equal to number of elements without multiplication by element size [-Werror=memset-elt-size]
When the decoding and presentation orders of pictures are different
(with GOP), the frames in YUV debug output would be in the decoding
order. This commit changes the kvazaar command line program to store the
reconstructed pictures in a buffer so that they can be output in the
presentation order.
Fixes#101.
Adds struct merge_candidates_t for holding the spatial and temporal
merge candidates. Changes functions with separate parameters for each
candidate to use the struct instead.
Limits video size so that the number of luma and chroma pixels can be
stored in an int. Fixes some integer overflows that resulted in
segmentation faults.
Finalization functions for frame and tile encoder states accessed the
frame and tile fields of the encoder state even though they might be
NULL. This is the case when the initialization of an encoder state
fails. Fixed by adding NULL checks.
Some of the fields in encoder_control_t were simply copies of the
corresponding fields in kvz_config. This commit drops the copied fields
in favor of using the fields in encoder_control_t.cfg directly.
The kvz_config struct is created by the user but kvazaar keeps a pointer
to it. It is easy to break things by modifying the configuration outside
kvazaar. In addition, kvazaar modifies the struct even though it is has
a const modifier.
This commit changes the field cfg in encoder_control_t to be a copy of
the kvz_config struct instead of a pointer, removing modifications to
the const struct and allowing users to do whatever they want with it
after opening the encoder.
The end of slice was being calculated incorrectly, which led to no tile
being created inside the slice, which led to an assert triggering.
This fixes the wrong end of slice calculation, but also disallows
wavefront rows from being created, if there would be only one.
The wavefront initialization code assumes there are always more than
one row, so the inter-frame dependency doesn't get added properly.
Fixes#153.
Main thread was stuck looping on pthread_cond_timedwait because
the abs time given on OS-X had already passed and the wait
returned immediately without releasing the mutex to allow worker
threads to proceed.
Fix was to use the gettimeofday, which returns real time instead
of monotonic, which is what pthread_cond_timedwait wants.
rdo.c:475:25: warning: absolute value function 'abs' given an argument of type 'int64_t' (aka 'long long') but has parameter
of type 'int' which may cause truncation of value [-Wabsolute-value]
current.cost = -abs(quant_cost_in_bits) + (bits << PRECISION_INC);
^
rdo.c:475:25: note: use function 'llabs' instead
current.cost = -abs(quant_cost_in_bits) + (bits << PRECISION_INC);
cfg.c:1024:74: warning: format specifies type 'size_t' (aka 'unsigned
long') but the argument has type 'unsigned long long'
[-Wformat]
fprintf(stderr, "Too large ROI size: %llu (maximum %zu).\n", size, SIZE_MAX);
This encapsulates tiles or WPP rows into their own slices, making
it possible to send them as soon as they are done, instead of waiting
for the other substreams to finish and coding the substream offsets
in the slice header.
These fixes allow more than one slice to be used to code a picture.
- Use correct number of bits to code the slice segment address.
- Don't offset_len_minus1 for slices without substreams.
Appending to the child stream doesn't work is the child is a leaf
slice state.
Simplifies flow by removing distinction between tile and slice. Now
that slice headers are written in the parent stream, there is zero
difference between tiles and slices from bitstream point of view.