Projects
Essentials
libde265
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 14
View file
libde265.changes
Changed
@@ -1,4 +1,47 @@ ------------------------------------------------------------------- +Tue Sep 15 10:26:14 UTC 2026 - Bjørn Lie <bjorn.lie@gmail.com> + +- Update to version 1.1.3: + + This release completes high bit depth decoding (up to 16 bit) + and repairs cross-component prediction, which had corrupted + 4:4:4 Range Extensions streams since v1.0.17. It is ABI- and + API-compatible with v1.1.2 and a drop-in replacement; no + functions or enum values were added. + + High bit depth decoding: + - Inter prediction above 12 bit was wrong from the first P/B + picture on. The fractional sample interpolation used shift1 = + BitDepth-8 instead of the Range Extensions' Min(4, + BitDepth-8), and the intermediate prediction samples were + kept in int16_t although they need max(14, BitDepth+2) bits. + The 16-bit kernels are now templated on the intermediate + sample type and use int32_t above 12 bit; 8- to 12-bit + streams are unaffected and keep their SSE paths. Explicit + weighted bi-prediction was broken in a second way: the + shortcut for identical motion vectors checked + weighted_pred_flag, which governs P slices, instead of + weighted_bipred_flag. + - Together with the fixes in v1.1.1 and v1.1.2 this completes + high bit depth support. Output is bit-exact against the HM 18 + reference decoder at 10, 12, 13, 14 and 16 bit, for mixed + luma/chroma bit depths and for 4:2:2, 4:4:4 and 4:0:0. Above + 12 bit motion compensation runs the scalar kernels; 8-bit + performance is unchanged. + + Range Extensions: + - Cross-component prediction corrupted every chroma block it + was applied to, a regression since v1.0.17. A cast added to + silence undefined behaviour on a left shift turned the + following arithmetic shift into a logical one, so every + negative luma residual became a large positive value. This + affects 4:4:4 streams only, but at every bit depth including + 8 bit. + - cabac_bypass_alignment_enabled_flag was parsed and then + ignored, so a stream using it desynchronized CABAC and + decoded to garbage without any diagnostic. It is now + implemented as specified in 9.3.4.3.6, and was the last Range + Extensions tool still missing. Both fixes are bit-exact + against HM 18. + +------------------------------------------------------------------- Thu Sep 3 06:04:55 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.1.2:
View file
libde265.spec
Changed
@@ -18,7 +18,7 @@ %define so_ver 0 Name: libde265 -Version: 1.1.2 +Version: 1.1.3 Release: 0 Summary: Open H.265 video codec implementation License: LGPL-3.0-only
View file
libde265-1.1.2.tar.gz/CMakeLists.txt -> libde265-1.1.3.tar.gz/CMakeLists.txt
Changed
@@ -2,7 +2,7 @@ project (libde265 LANGUAGES C CXX - VERSION 1.1.2 + VERSION 1.1.3 ) # Auto-compute BCD-encoded numeric version from project version. @@ -35,7 +35,7 @@ # Programs linked against libde265.so.0 will work with any libde265.so.0.x.y. # set(DE265_SOVERSION 0) -set(DE265_LIBRARY_VERSION "0.2.2") +set(DE265_LIBRARY_VERSION "0.2.3") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)
View file
libde265-1.1.2.tar.gz/README.md -> libde265-1.1.3.tar.gz/README.md
Changed
@@ -8,9 +8,13 @@ It is written from scratch and has a plain C API to enable a simple integration into other software. -libde265 supports WPP and tile-based multithreading and includes SSE optimizations. -The decoder includes all features of the Main profile and correctly decodes almost all -conformance streams (see wiki page(https://github.com/strukturag/libde265/wiki/Decoder-conformance)). +libde265 supports WPP and tile-based multithreading and includes SSE, AVX2 and AVX-512 +optimizations. +The decoder includes all features of the Main profile, and it supports Main 10 and the +Range Extensions: bit depths from 8 to 16 bit (independently for luma and chroma), the +4:2:0, 4:2:2, 4:4:4 and monochrome chroma formats, and the Range Extensions coding tools. +It correctly decodes almost all conformance streams (see +wiki page(https://github.com/strukturag/libde265/wiki/Decoder-conformance)). A list of supported features are available in the wiki(https://github.com/strukturag/libde265/wiki/Supported-decoding-features).
View file
libde265-1.1.2.tar.gz/libde265/acceleration.h -> libde265-1.1.3.tar.gz/libde265/acceleration.h
Changed
@@ -26,6 +26,12 @@ #include <assert.h> +// Highest bit depth at which the intermediate motion-compensation samples +// (predSamplesLX, spec 8.5.3.3.3) still fit into int16_t. Above it, the +// "_16_32" kernels with int32_t intermediates are used. +constexpr int MC_MAX_BIT_DEPTH_INT16 = 12; + + struct acceleration_functions { void (*put_weighted_pred_avg_8)(uint8_t *_dst, ptrdiff_t dststride, @@ -64,22 +70,63 @@ int w1,int o1, int w2,int o2, int log2WD, int bit_depth); + // --- BitDepth > MC_MAX_BIT_DEPTH_INT16 --- + // The intermediate prediction samples (predSamplesLX, spec 8.5.3.3.3) have + // max(14, BitDepth+2) bits plus the overshoot of the interpolation filters, + // so above 12 bits they do not fit into int16_t anymore. These variants of the + // 16-bit pixel kernels take int32_t intermediates instead. + + void (*put_weighted_pred_avg_16_32)(uint16_t *_dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, int bit_depth); + + void (*put_unweighted_pred_16_32)(uint16_t *_dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, int bit_depth); + + void (*put_weighted_pred_16_32)(uint16_t *_dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, + int w,int o,int log2WD, int bit_depth); + void (*put_weighted_bipred_16_32)(uint16_t *_dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, + int w1,int o1, int w2,int o2, int log2WD, int bit_depth); + + + // Dispatch on bit depth; the int32_t overloads are for BitDepth > MC_MAX_BIT_DEPTH_INT16 only. + void put_weighted_pred_avg(void *_dst, ptrdiff_t dststride, const int16_t *src1, const int16_t *src2, ptrdiff_t srcstride, int width, int height, int bit_depth) const; + void put_weighted_pred_avg(void *_dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, int bit_depth) const; void put_unweighted_pred(void *_dst, ptrdiff_t dststride, const int16_t *src, ptrdiff_t srcstride, int width, int height, int bit_depth) const; + void put_unweighted_pred(void *_dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, int bit_depth) const; void put_weighted_pred(void *_dst, ptrdiff_t dststride, const int16_t *src, ptrdiff_t srcstride, int width, int height, int w,int o,int log2WD, int bit_depth) const; + void put_weighted_pred(void *_dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, + int w,int o,int log2WD, int bit_depth) const; + void put_weighted_bipred(void *_dst, ptrdiff_t dststride, const int16_t *src1, const int16_t *src2, ptrdiff_t srcstride, int width, int height, int w1,int o1, int w2,int o2, int log2WD, int bit_depth) const; + void put_weighted_bipred(void *_dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, + int w1,int o1, int w2,int o2, int log2WD, int bit_depth) const; @@ -120,6 +167,31 @@ int16_t* mcbuffer, int bit_depth); + // --- BitDepth > MC_MAX_BIT_DEPTH_INT16: 16-bit pixels, int32_t intermediates (see above) --- + + void (*put_hevc_epel_16_32)(int32_t *dst, ptrdiff_t dststride, + const uint16_t *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth); + void (*put_hevc_epel_h_16_32)(int32_t *dst, ptrdiff_t dststride, + const uint16_t *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth); + void (*put_hevc_epel_v_16_32)(int32_t *dst, ptrdiff_t dststride, + const uint16_t *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth); + void (*put_hevc_epel_hv_16_32)(int32_t *dst, ptrdiff_t dststride, + const uint16_t *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth); + + // One generic kernel for all fractional positions (including full-sample), + // since this path is not performance critical and per-position copies of + // the filter would cost ~50 KB of code. + void (*put_hevc_qpel_16_32)(int32_t *dst, ptrdiff_t dststride, + const uint16_t *src, ptrdiff_t srcstride, int width, int height, + int32_t* mcbuffer, int xFrac, int yFrac, int bit_depth); + + + // Dispatch on bit depth; the int32_t overloads are for BitDepth > MC_MAX_BIT_DEPTH_INT16 only. + void put_hevc_epel(int16_t *dst, ptrdiff_t dststride, const void *src, ptrdiff_t srcstride, int width, int height, int mx, int my, int16_t* mcbuffer, int bit_depth) const; @@ -137,6 +209,23 @@ const void *src, ptrdiff_t srcstride, int width, int height, int16_t* mcbuffer, int dX,int dY, int bit_depth) const; + void put_hevc_epel(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const; + void put_hevc_epel_h(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const; + void put_hevc_epel_v(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const; + void put_hevc_epel_hv(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const; + + void put_hevc_qpel(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int32_t* mcbuffer, int dX,int dY, int bit_depth) const; + // --- inverse transforms --- @@ -368,6 +457,88 @@ put_hevc_qpel_16dXdY(dst,dststride,(const uint16_t*)src,srcstride,width,height,mcbuffer, bit_depth); } + +// --- BitDepth > MC_MAX_BIT_DEPTH_INT16: int32_t intermediates, always 16-bit pixels --- + +inline void acceleration_functions::put_weighted_pred_avg(void* _dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, int bit_depth) const +{ + assert(bit_depth > 8); + put_weighted_pred_avg_16_32((uint16_t*)_dst,dststride,src1,src2,srcstride,width,height,bit_depth); +} + + +inline void acceleration_functions::put_unweighted_pred(void* _dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, int bit_depth) const +{ + assert(bit_depth > 8); + put_unweighted_pred_16_32((uint16_t*)_dst,dststride,src,srcstride,width,height,bit_depth); +} + + +inline void acceleration_functions::put_weighted_pred(void* _dst, ptrdiff_t dststride, + const int32_t *src, ptrdiff_t srcstride, + int width, int height, + int w,int o,int log2WD, int bit_depth) const +{ + assert(bit_depth > 8); + put_weighted_pred_16_32((uint16_t*)_dst,dststride,src,srcstride,width,height,w,o,log2WD,bit_depth); +} + + +inline void acceleration_functions::put_weighted_bipred(void* _dst, ptrdiff_t dststride, + const int32_t *src1, const int32_t *src2, ptrdiff_t srcstride, + int width, int height, + int w1,int o1, int w2,int o2, int log2WD, int bit_depth) const +{ + assert(bit_depth > 8); + put_weighted_bipred_16_32((uint16_t*)_dst,dststride,src1,src2,srcstride, width,height, w1,o1,w2,o2,log2WD,bit_depth); +} + + +inline void acceleration_functions::put_hevc_epel(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const +{ + assert(bit_depth > 8); + put_hevc_epel_16_32(dst,dststride,(const uint16_t*)src,srcstride,width,height,mx,my,mcbuffer, bit_depth); +} + +inline void acceleration_functions::put_hevc_epel_h(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const +{ + assert(bit_depth > 8); + put_hevc_epel_h_16_32(dst,dststride,(const uint16_t*)src,srcstride,width,height,mx,my,mcbuffer,bit_depth); +} + +inline void acceleration_functions::put_hevc_epel_v(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const +{ + assert(bit_depth > 8); + put_hevc_epel_v_16_32(dst,dststride,(const uint16_t*)src,srcstride,width,height,mx,my,mcbuffer, bit_depth); +} + +inline void acceleration_functions::put_hevc_epel_hv(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int mx, int my, int32_t* mcbuffer, int bit_depth) const +{ + assert(bit_depth > 8); + put_hevc_epel_hv_16_32(dst,dststride,(const uint16_t*)src,srcstride,width,height,mx,my,mcbuffer, bit_depth); +} + +inline void acceleration_functions::put_hevc_qpel(int32_t *dst, ptrdiff_t dststride, + const void *src, ptrdiff_t srcstride, int width, int height, + int32_t* mcbuffer, int dX,int dY, int bit_depth) const +{ + assert(bit_depth > 8); + put_hevc_qpel_16_32(dst,dststride,(const uint16_t*)src,srcstride,width,height,mcbuffer, dX,dY, bit_depth); +} + + template <> inline void acceleration_functions::transform_skip<uint8_t>(uint8_t *dst, const int16_t *coeffs,ptrdiff_t stride, int bit_depth) const { transform_skip_8(dst,coeffs,stride); } template <> inline void acceleration_functions::transform_skip<uint16_t>(uint16_t *dst, const int16_t *coeffs, ptrdiff_t stride, int bit_depth) const { transform_skip_16(dst,coeffs,stride, bit_depth); }
View file
libde265-1.1.2.tar.gz/libde265/cabac.cc -> libde265-1.1.3.tar.gz/libde265/cabac.cc
Changed
@@ -371,6 +371,17 @@ // When we read past the end of the bitstream (which should only happen on faulty bitstreams), // we will eventually only return zeros. +/* (9.3.4.3.6) Alignment process prior to aligned bypass decoding. Invoked before the + bypass-coded coeff_sign_flag / coeff_abs_level_remaining of a sub-block carrying escape + data when cabac_bypass_alignment_enabled_flag is set. Bypass decoding leaves + ivlCurrRange untouched, so a single call covers the whole run of bypass bins after it. +*/ +void CABAC_decoder::align_bypass() +{ + range = 256; +} + + int CABAC_decoder::decode_bypass() { #ifdef DE265_CABAC_ASM_X86_64
View file
libde265-1.1.2.tar.gz/libde265/cabac.h -> libde265-1.1.3.tar.gz/libde265/cabac.h
Changed
@@ -34,6 +34,7 @@ int decode_term_bit(); int decode_bypass(); + void align_bypass(); int decode_TU_bypass(int cMax); uint32_t decode_FL_bypass(int nBits); int decode_TR_bypass(int cRiceParam, int cTRMax);
View file
libde265-1.1.2.tar.gz/libde265/de265.h -> libde265-1.1.3.tar.gz/libde265/de265.h
Changed
@@ -352,6 +352,25 @@ int visible_height; // convenience, height - crop_top - crop_bottom } de265_image_spec; +/* Custom image buffer allocation. + + get_buffer() has to provide the image planes by calling de265_set_image_plane() + for each of them. The buffers have to be large enough for the image described by + 'spec', taking spec->alignment into account when computing the stride, plus at + least 16 trailing bytes beyond the last row. The SIMD code processes whole vectors + and may read up to a vector past the pixels it actually uses, so a plane allocated + with no slack is read out of bounds. Allocate the trailing bytes unconditionally; + whether they are touched depends on which SIMD paths libde265 was built with and + on the CPU it runs on. + + The memory handed back has to be zero-initialized (or otherwise fully initialized). + libde265 does not clear buffers obtained from get_buffer(); only the built-in + allocator returned by de265_get_default_image_allocation_functions() clears them + itself. If an allocator returns uninitialized memory, any part of an image that the + decoder does not write -- for example a picture that a corrupted stream covers only + partially with slices -- shows up in the decoded output, exposing whatever the + application previously kept in that memory. +*/ typedef struct de265_image_allocation { int (*get_buffer)(de265_decoder_context* ctx, // first parameter deprecated
View file
libde265-1.1.2.tar.gz/libde265/decctx.cc -> libde265-1.1.3.tar.gz/libde265/decctx.cc
Changed
@@ -25,6 +25,7 @@ #include "deblock.h" #include <algorithm> +#include <utility> #include <string.h> #include <assert.h> #include <stdlib.h> @@ -92,7 +93,9 @@ slice_unit::~slice_unit() { - ctx->nal_parser.free_NAL_unit(nal); + // Return our NAL to the reuse pool. (Letting the unique_ptr delete it would be + // memory-safe too, but would bypass pooling.) + ctx->nal_parser.free_NAL_unit(std::move(nal)); if (thread_contexts) { delete thread_contexts; @@ -503,7 +506,7 @@ } -de265_error decoder_context::read_slice_NAL(bitreader& reader, NAL_unit* nal, nal_header& nal_hdr) +de265_error decoder_context::read_slice_NAL(bitreader& reader, std::unique_ptr<NAL_unit> nal, nal_header& nal_hdr) { logdebug(LogHeaders,"---> read slice segment header\n"); @@ -515,7 +518,7 @@ de265_error err = shdr->read(&reader,this, &continueDecoding); if (!continueDecoding) { if (img) { img->integrity = INTEGRITY_NOT_DECODED; } - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); delete shdr; return err; } @@ -528,7 +531,7 @@ if (process_slice_segment_header(shdr, &err, nal->pts, &nal_hdr, nal->user_data) == false) { if (img!=nullptr) img->integrity = INTEGRITY_NOT_DECODED; - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); delete shdr; return err; } @@ -545,7 +548,7 @@ headerLength); if (skipped > shdr->entry_point_offseti) { add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); delete shdr; return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } @@ -585,7 +588,7 @@ previous_slice_header = shdr; slice_unit* sliceunit = new slice_unit(this); - sliceunit->nal = nal; + sliceunit->nal = std::move(nal); sliceunit->shdr = shdr; sliceunit->reader = reader; @@ -595,7 +598,7 @@ image_units.back()->slice_units.push_back(sliceunit); } else { - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); delete shdr; } @@ -1133,7 +1136,13 @@ } -de265_error decoder_context::decode_NAL(NAL_unit* nal) +// Ownership: decode_NAL() receives the NAL by moved-in unique_ptr and releases +// it on every return path. Parameter-set, SEI and discarded NALs are returned to +// the pool directly here; slice NALs are moved into read_slice_NAL(), which +// either releases the NAL or moves it into a slice_unit that owns it for the rest +// of the image_unit's lifetime. Because ownership is a unique_ptr, the NAL cannot +// be released twice. +de265_error decoder_context::decode_NAL(std::unique_ptr<NAL_unit> nal) { //return decode_NAL_OLD(nal); @@ -1146,7 +1155,7 @@ nal_header nal_hdr; err = nal_hdr.read(&reader); if (err != DE265_OK) { - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); return err; } ctx->process_nal_hdr(&nal_hdr); @@ -1154,7 +1163,7 @@ if (nal_hdr.nuh_layer_id > 0) { // Discard all NAL units with nuh_layer_id > 0 // These will have to be handled by an SHVC decoder. - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); return DE265_OK; } @@ -1176,43 +1185,43 @@ //printf("hTid: %d\n", current_HighestTid); if (nal_hdr.nuh_temporal_id > current_HighestTid) { - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); return DE265_OK; } if (nal_hdr.nal_unit_type<32) { - err = read_slice_NAL(reader, nal, nal_hdr); + err = read_slice_NAL(reader, std::move(nal), nal_hdr); } else switch (nal_hdr.nal_unit_type) { case NAL_UNIT_VPS_NUT: err = read_vps_NAL(reader); - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; case NAL_UNIT_SPS_NUT: err = read_sps_NAL(reader); - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; case NAL_UNIT_PPS_NUT: err = read_pps_NAL(reader); - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; case NAL_UNIT_PREFIX_SEI_NUT: case NAL_UNIT_SUFFIX_SEI_NUT: err = read_sei_NAL(reader, nal_hdr.nal_unit_type==NAL_UNIT_SUFFIX_SEI_NUT); - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; case NAL_UNIT_EOS_NUT: ctx->FirstAfterEndOfSequenceNAL = true; - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; default: - nal_parser.free_NAL_unit(nal); + nal_parser.free_NAL_unit(std::move(nal)); break; } @@ -1268,10 +1277,13 @@ bool did_work = false; if (ctx->nal_parser.get_NAL_queue_length()) { // number_of_NAL_units_pending()) { - NAL_unit* nal = ctx->nal_parser.pop_from_NAL_queue(); + std::unique_ptr<NAL_unit> nal = ctx->nal_parser.pop_from_NAL_queue(); assert(nal); - err = ctx->decode_NAL(nal); - // ctx->nal_parser.free_NAL_unit(nal); TODO: do not free NAL with new loop + + // Ownership of the dequeued NAL moves into decode_NAL(), which releases it on + // every path (directly, or via a slice_unit that returns it to the pool when + // the image_unit is destroyed). Nothing to free here. + err = ctx->decode_NAL(std::move(nal)); did_work=true; } else if (ctx->nal_parser.is_end_of_frame() == true &&
View file
libde265-1.1.2.tar.gz/libde265/decctx.h -> libde265-1.1.3.tar.gz/libde265/decctx.h
Changed
@@ -145,7 +145,7 @@ slice_unit(decoder_context* decctx); ~slice_unit(); - NAL_unit* nal; // we are the owner + std::unique_ptr<NAL_unit> nal; // we are the owner slice_segment_header* shdr; // not the owner (de265_image is owner) bitreader reader; @@ -333,7 +333,7 @@ uint8_t get_nal_unit_type() const { return nal_unit_type; } bool get_RapPicFlag() const { return RapPicFlag; } - de265_error decode_NAL(NAL_unit* nal); + de265_error decode_NAL(std::unique_ptr<NAL_unit> nal); de265_error decode(int* more); de265_error decode_some(bool* did_work); @@ -405,7 +405,7 @@ de265_error read_pps_NAL(bitreader&); de265_error read_sei_NAL(bitreader& reader, bool suffix); de265_error read_eos_NAL(bitreader& reader); - de265_error read_slice_NAL(bitreader&, NAL_unit* nal, nal_header& nal_hdr); + de265_error read_slice_NAL(bitreader&, std::unique_ptr<NAL_unit> nal, nal_header& nal_hdr); private: // --- internal data ---
View file
libde265-1.1.2.tar.gz/libde265/fallback-motion.cc -> libde265-1.1.3.tar.gz/libde265/fallback-motion.cc
Changed
@@ -28,6 +28,7 @@ #endif #include <assert.h> +#include <algorithm> void put_unweighted_pred_8_fallback(uint8_t *dst, ptrdiff_t dststride, @@ -161,8 +162,13 @@ +// The 16-bit pixel kernels are templates on the type of the intermediate +// prediction samples (predSamplesLX in the spec): int16_t for BitDepth <= 12, +// int32_t above (see acceleration.h). + +template <class inter_t> void put_unweighted_pred_16_fallback(uint16_t *dst, ptrdiff_t dststride, - const int16_t *src, ptrdiff_t srcstride, + const inter_t *src, ptrdiff_t srcstride, int width, int height, int bit_depth) { // shift1 per HEVC v2 (10/2014) spec 8.5.3.3.4.2: Max(2, 14 - BitDepth). @@ -174,7 +180,7 @@ assert((width&1)==0); for (int y=0;y<height;y++) { - const int16_t* in = &srcy*srcstride; + const inter_t* in = &srcy*srcstride; uint16_t* out = &dsty*dststride; for (int x=0;x<width;x+=2) { @@ -185,19 +191,23 @@ } } +template void put_unweighted_pred_16_fallback<int16_t>(uint16_t*, ptrdiff_t, const int16_t*, ptrdiff_t, int, int, int); +template void put_unweighted_pred_16_fallback<int32_t>(uint16_t*, ptrdiff_t, const int32_t*, ptrdiff_t, int, int, int); + #include <stdlib.h> +template <class inter_t> void put_weighted_pred_16_fallback(uint16_t *dst, ptrdiff_t dststride, - const int16_t *src, ptrdiff_t srcstride, + const inter_t *src, ptrdiff_t srcstride, int width, int height, int w,int o,int log2WD, int bit_depth) { - assert(log2WD>=1); // TODO + assert(log2WD>=1); // log2WD = log2_weight_denom + Max(2, 14-BitDepth) >= 2 const int rnd = (1<<(log2WD-1)); for (int y=0;y<height;y++) { - const int16_t* in = &srcy*srcstride; + const inter_t* in = &srcy*srcstride; uint16_t* out = &dsty*dststride; for (int x=0;x<width;x++) { @@ -207,18 +217,24 @@ } } +template void put_weighted_pred_16_fallback<int16_t>(uint16_t*, ptrdiff_t, const int16_t*, ptrdiff_t, int, int, int, int, int, int); +template void put_weighted_pred_16_fallback<int32_t>(uint16_t*, ptrdiff_t, const int32_t*, ptrdiff_t, int, int, int, int, int, int); + +template <class inter_t> void put_weighted_bipred_16_fallback(uint16_t *dst, ptrdiff_t dststride, - const int16_t *src1, const int16_t *src2, ptrdiff_t srcstride, + const inter_t *src1, const inter_t *src2, ptrdiff_t srcstride, int width, int height, int w1,int o1, int w2,int o2, int log2WD, int bit_depth) { - assert(log2WD>=1); // TODO + assert(log2WD>=1); // log2WD = log2_weight_denom + Max(2, 14-BitDepth) >= 2 + // Worst case at BitDepth 16 (int32_t intermediates): |predSample| < 2^20, |w| <= 255, + // |o1+o2+1| <= 2^16, log2WD <= 9 -> the sum stays below 2^29 and fits into int. const int rnd = static_cast<int>(static_cast<unsigned int>(o1+o2+1) << log2WD); for (int y=0;y<height;y++) { - const int16_t* in1 = &src1y*srcstride; - const int16_t* in2 = &src2y*srcstride; + const inter_t* in1 = &src1y*srcstride; + const inter_t* in2 = &src2y*srcstride; uint16_t* out = &dsty*dststride; for (int x=0;x<width;x++) { @@ -228,9 +244,13 @@ } } +template void put_weighted_bipred_16_fallback<int16_t>(uint16_t*, ptrdiff_t, const int16_t*, const int16_t*, ptrdiff_t, int, int, int, int, int, int, int, int); +template void put_weighted_bipred_16_fallback<int32_t>(uint16_t*, ptrdiff_t, const int32_t*, const int32_t*, ptrdiff_t, int, int, int, int, int, int, int, int); + +template <class inter_t> void put_weighted_pred_avg_16_fallback(uint16_t *dst, ptrdiff_t dststride, - const int16_t *src1, const int16_t *src2, + const inter_t *src1, const inter_t *src2, ptrdiff_t srcstride, int width, int height, int bit_depth) { @@ -243,8 +263,8 @@ assert((width&1)==0); for (int y=0;y<height;y++) { - const int16_t* in1 = &src1y*srcstride; - const int16_t* in2 = &src2y*srcstride; + const inter_t* in1 = &src1y*srcstride; + const inter_t* in2 = &src2y*srcstride; uint16_t* out = &dsty*dststride; for (int x=0;x<width;x+=2) { @@ -255,6 +275,9 @@ } } +template void put_weighted_pred_avg_16_fallback<int16_t>(uint16_t*, ptrdiff_t, const int16_t*, const int16_t*, ptrdiff_t, int, int, int); +template void put_weighted_pred_avg_16_fallback<int32_t>(uint16_t*, ptrdiff_t, const int32_t*, const int32_t*, ptrdiff_t, int, int, int); + @@ -279,10 +302,11 @@ } -void put_epel_16_fallback(int16_t *out, ptrdiff_t out_stride, +template <class inter_t> +void put_epel_16_fallback(inter_t *out, ptrdiff_t out_stride, const uint16_t *src, ptrdiff_t src_stride, int width, int height, - int mx, int my, int16_t* mcbuffer, int bit_depth) + int mx, int my, inter_t* mcbuffer, int bit_depth) { // shift3 per HEVC v2 (10/2014) spec 8.5.3.3.3.3 (chroma): Max(2, 14 - BitDepth). // The Max() was added with the Range Extensions in v2 to handle BitDepth up to 16; @@ -290,7 +314,7 @@ int shift3 = std::max(2, 14 - bit_depth); for (int y=0;y<height;y++) { - int16_t* o = &outy*out_stride; + inter_t* o = &outy*out_stride; const uint16_t* i = &srcy*src_stride; for (int x=0;x<width;x++) { @@ -301,14 +325,20 @@ } } +template void put_epel_16_fallback<int16_t>(int16_t*, ptrdiff_t, const uint16_t*, ptrdiff_t, int, int, int, int, int16_t*, int); +template void put_epel_16_fallback<int32_t>(int32_t*, ptrdiff_t, const uint16_t*, ptrdiff_t, int, int, int, int, int32_t*, int); -template <class pixel_t> -void put_epel_hv_fallback(int16_t *dst, ptrdiff_t dst_stride, + +template <class pixel_t, class inter_t> +void put_epel_hv_fallback(inter_t *dst, ptrdiff_t dst_stride, const pixel_t *src, ptrdiff_t src_stride, int nPbWC, int nPbHC, - int xFracC, int yFracC, int16_t* mcbuffer, int bit_depth) + int xFracC, int yFracC, inter_t* mcbuffer, int bit_depth) { - const int shift1 = bit_depth-8; + // shift1 per HEVC v2 (10/2014) spec 8.5.3.3.3.3 (chroma): Min(4, BitDepth - 8). + // The Min() was added with the Range Extensions in v2 for BitDepth > 12: the + // intermediate samples then keep BitDepth+2 bits instead of 14 (see shift3). + const int shift1 = std::min(4, bit_depth-8); const int shift2 = 6; //const int shift3 = 6; @@ -320,7 +350,7 @@ int nPbH_extra = extra_top + nPbHC + extra_bottom; - int16_t* tmp2buf = (int16_t*)alloca( nPbWC * nPbH_extra * sizeof(int16_t) ); + inter_t* tmp2buf = (inter_t*)alloca( nPbWC * nPbH_extra * sizeof(inter_t) ); /* int nPbW_extra = extra_left + nPbWC + extra_right; @@ -351,7 +381,7 @@ const pixel_t* p = &srcy*src_stride - extra_left; for (int x=0;x<nPbWC;x++) { - int16_t v; + int v; switch (xFracC) { case 0: v = p1; break; case 1: v = (-2*p0+58*p1+10*p2-2*p3)>>shift1; break; @@ -379,10 +409,10 @@ int vshift = (xFracC==0 ? shift1 : shift2); for (int x=0;x<nPbWC;x++) { - int16_t* p = &tmp2bufx*nPbH_extra; + inter_t* p = &tmp2bufx*nPbH_extra; for (int y=0;y<nPbHC;y++) { - int16_t v; + int v; //logtrace(LogMotion,"%x %x %x %x %x %x %x\n",p0,p1,p2,p3,p4,p5,p6); switch (yFracC) { @@ -416,15 +446,20 @@ template -void put_epel_hv_fallback<uint8_t>(int16_t *dst, ptrdiff_t dst_stride, - const uint8_t *src, ptrdiff_t src_stride, - int nPbWC, int nPbHC, - int xFracC, int yFracC, int16_t* mcbuffer, int bit_depth); +void put_epel_hv_fallback<uint8_t,int16_t>(int16_t *dst, ptrdiff_t dst_stride, + const uint8_t *src, ptrdiff_t src_stride, + int nPbWC, int nPbHC, + int xFracC, int yFracC, int16_t* mcbuffer, int bit_depth); +template +void put_epel_hv_fallback<uint16_t,int16_t>(int16_t *dst, ptrdiff_t dst_stride, + const uint16_t *src, ptrdiff_t src_stride, + int nPbWC, int nPbHC, + int xFracC, int yFracC, int16_t* mcbuffer, int bit_depth); template -void put_epel_hv_fallback<uint16_t>(int16_t *dst, ptrdiff_t dst_stride, - const uint16_t *src, ptrdiff_t src_stride, - int nPbWC, int nPbHC, - int xFracC, int yFracC, int16_t* mcbuffer, int bit_depth); +void put_epel_hv_fallback<uint16_t,int32_t>(int32_t *dst, ptrdiff_t dst_stride, + const uint16_t *src, ptrdiff_t src_stride, + int nPbWC, int nPbHC, + int xFracC, int yFracC, int32_t* mcbuffer, int bit_depth); @@ -461,9 +496,10 @@ } -void put_qpel_0_0_fallback_16(int16_t *out, ptrdiff_t out_stride, +template <class inter_t> +void put_qpel_0_0_fallback_16(inter_t *out, ptrdiff_t out_stride, const uint16_t *src, ptrdiff_t srcstride, - int nPbW, int nPbH, int16_t* mcbuffer, int bit_depth) + int nPbW, int nPbH, inter_t* mcbuffer, int bit_depth) { //const int shift1 = bit_depth-8; //const int shift2 = 6; @@ -476,7 +512,7 @@ for (int y=0;y<nPbH;y++) { const uint16_t* p = src + srcstride*y; - int16_t* o = out + out_stride*y; + inter_t* o = out + out_stride*y; for (int x=0;x<nPbW;x++) { *o++ = *p++ << shift3; @@ -484,15 +520,18 @@ } } +template void put_qpel_0_0_fallback_16<int16_t>(int16_t*, ptrdiff_t, const uint16_t*, ptrdiff_t, int, int, int16_t*, int); +template void put_qpel_0_0_fallback_16<int32_t>(int32_t*, ptrdiff_t, const uint16_t*, ptrdiff_t, int, int, int32_t*, int); + static int extra_before4 = { 0,3,3,2 }; static int extra_after 4 = { 0,3,4,4 }; -template <class pixel_t> -void put_qpel_fallback(int16_t *out, ptrdiff_t out_stride, +template <class pixel_t, class inter_t> +void put_qpel_fallback(inter_t *out, ptrdiff_t out_stride, const pixel_t *src, ptrdiff_t srcstride, - int nPbW, int nPbH, int16_t* mcbuffer, + int nPbW, int nPbH, inter_t* mcbuffer, int xFracL, int yFracL, int bit_depth) { int extra_left = extra_beforexFracL; @@ -503,7 +542,10 @@ //int nPbW_extra = extra_left + nPbW + extra_right; int nPbH_extra = extra_top + nPbH + extra_bottom; - const int shift1 = bit_depth-8; + // shift1 per HEVC v2 (10/2014) spec 8.5.3.3.3.2 (luma): Min(4, BitDepth - 8). + // The Min() was added with the Range Extensions in v2 for BitDepth > 12: the + // intermediate samples then keep BitDepth+2 bits instead of 14 (see shift3). + const int shift1 = std::min(4, bit_depth-8); const int shift2 = 6; @@ -513,7 +555,7 @@ case 0: for (int y=-extra_top;y<nPbH+extra_bottom;y++) { const pixel_t* p = src + srcstride*y - extra_left; - int16_t* o = &mcbuffery+extra_top; + inter_t* o = &mcbuffery+extra_top; for (int x=0;x<nPbW;x++) { *o = *p; @@ -525,7 +567,7 @@ case 1: for (int y=-extra_top;y<nPbH+extra_bottom;y++) { const pixel_t* p = src + srcstride*y - extra_left; - int16_t* o = &mcbuffery+extra_top; + inter_t* o = &mcbuffery+extra_top; for (int x=0;x<nPbW;x++) { *o = (-p0+4*p1-10*p2+58*p3+17*p4 -5*p5 +p6)>>shift1; @@ -537,7 +579,7 @@ case 2: for (int y=-extra_top;y<nPbH+extra_bottom;y++) { const pixel_t* p = src + srcstride*y - extra_left; - int16_t* o = &mcbuffery+extra_top; + inter_t* o = &mcbuffery+extra_top; for (int x=0;x<nPbW;x++) { *o = (-p0+4*p1-11*p2+40*p3+40*p4-11*p5+4*p6-p7)>>shift1; @@ -549,7 +591,7 @@ case 3: for (int y=-extra_top;y<nPbH+extra_bottom;y++) { const pixel_t* p = src + srcstride*y - extra_left; - int16_t* o = &mcbuffery+extra_top; + inter_t* o = &mcbuffery+extra_top; for (int x=0;x<nPbW;x++) { *o = ( p0-5*p1+17*p2+58*p3-10*p4 +4*p5 -p6)>>shift1; @@ -577,8 +619,8 @@ switch (yFracL) { case 0: for (int x=0;x<nPbW;x++) { - const int16_t* p = &mcbufferx*nPbH_extra; - int16_t* o = &outx; + const inter_t* p = &mcbufferx*nPbH_extra; + inter_t* o = &outx; for (int y=0;y<nPbH;y++) { *o = *p; @@ -589,8 +631,8 @@ break; case 1: for (int x=0;x<nPbW;x++) { - const int16_t* p = &mcbufferx*nPbH_extra; - int16_t* o = &outx; + const inter_t* p = &mcbufferx*nPbH_extra; + inter_t* o = &outx; for (int y=0;y<nPbH;y++) { *o = (-p0+4*p1-10*p2+58*p3+17*p4 -5*p5 +p6)>>vshift; @@ -601,8 +643,8 @@ break; case 2: for (int x=0;x<nPbW;x++) { - const int16_t* p = &mcbufferx*nPbH_extra; - int16_t* o = &outx; + const inter_t* p = &mcbufferx*nPbH_extra; + inter_t* o = &outx; for (int y=0;y<nPbH;y++) { *o = (-p0+4*p1-11*p2+40*p3+40*p4-11*p5+4*p6-p7)>>vshift; @@ -613,8 +655,8 @@ break; case 3: for (int x=0;x<nPbW;x++) { - const int16_t* p = &mcbufferx*nPbH_extra; - int16_t* o = &outx; + const inter_t* p = &mcbufferx*nPbH_extra; + inter_t* o = &outx; for (int y=0;y<nPbH;y++) { *o = ( p0-5*p1+17*p2+58*p3-10*p4 +4*p5 -p6)>>vshift; @@ -643,6 +685,21 @@ { put_qpel_fallback(out,out_stride, src,srcstride, nPbW,nPbH,mcbuffer,x,y, 8 ); } +// The int32_t variant (BitDepth > 12) is not performance critical: one generic +// kernel for all fractional positions instead of 16 specialized copies. +void put_qpel_fallback_16_32(int32_t *out, ptrdiff_t out_stride, + const uint16_t *src, ptrdiff_t srcstride, + int nPbW, int nPbH, int32_t* mcbuffer, + int xFracL, int yFracL, int bit_depth) +{ + if (xFracL==0 && yFracL==0) { + put_qpel_0_0_fallback_16(out,out_stride, src,srcstride, nPbW,nPbH,mcbuffer, bit_depth); + } + else { + put_qpel_fallback(out,out_stride, src,srcstride, nPbW,nPbH,mcbuffer, xFracL,yFracL, bit_depth); + } +} + #define QPEL16(x,y) void put_qpel_ ## x ## _ ## y ## _fallback_16(int16_t *out, ptrdiff_t out_stride, \ const uint16_t *src, ptrdiff_t srcstride, \ int nPbW, int nPbH, int16_t* mcbuffer, int bit_depth) \
View file
libde265-1.1.2.tar.gz/libde265/fallback-motion.h -> libde265-1.1.3.tar.gz/libde265/fallback-motion.h
Changed
@@ -43,21 +43,29 @@ int width, int height, int w1,int o1, int w2,int o2, int log2WD); +// The 16-bit pixel kernels are templates on the type of the intermediate +// prediction samples (inter_t): int16_t up to MC_MAX_BIT_DEPTH_INT16 (see +// acceleration.h), int32_t above. Instantiated for both types in fallback-motion.cc. + +template <class inter_t> void put_weighted_pred_avg_16_fallback(uint16_t *dst, ptrdiff_t dststride, - const int16_t *src1, const int16_t *src2, + const inter_t *src1, const inter_t *src2, ptrdiff_t srcstride, int width, int height, int bit_depth); +template <class inter_t> void put_unweighted_pred_16_fallback(uint16_t *_dst, ptrdiff_t dststride, - const int16_t *src, ptrdiff_t srcstride, + const inter_t *src, ptrdiff_t srcstride, int width, int height, int bit_depth); +template <class inter_t> void put_weighted_pred_16_fallback(uint16_t *_dst, ptrdiff_t dststride, - const int16_t *src, ptrdiff_t srcstride, + const inter_t *src, ptrdiff_t srcstride, int width, int height, int w,int o,int log2WD, int bit_depth); +template <class inter_t> void put_weighted_bipred_16_fallback(uint16_t *_dst, ptrdiff_t dststride, - const int16_t *src1, const int16_t *src2, ptrdiff_t srcstride, + const inter_t *src1, const inter_t *src2, ptrdiff_t srcstride, int width, int height, int w1,int o1, int w2,int o2, int log2WD, int bit_depth); @@ -68,16 +76,17 @@ int width, int height, int mx, int my, int16_t* mcbuffer); -void put_epel_16_fallback(int16_t *out, ptrdiff_t out_stride, +template <class inter_t> +void put_epel_16_fallback(inter_t *out, ptrdiff_t out_stride, const uint16_t *src, ptrdiff_t src_stride, int width, int height, - int mx, int my, int16_t* mcbuffer, int bit_depth); + int mx, int my, inter_t* mcbuffer, int bit_depth); -template <class pixel_t> -void put_epel_hv_fallback(int16_t *dst, ptrdiff_t dststride, +template <class pixel_t, class inter_t> +void put_epel_hv_fallback(inter_t *dst, ptrdiff_t dststride, const pixel_t *_src, ptrdiff_t srcstride, int width, int height, - int mx, int my, int16_t* mcbuffer, int bit_depth); + int mx, int my, inter_t* mcbuffer, int bit_depth); #define QPEL(x,y) void put_qpel_ ## x ## _ ## y ## _fallback(int16_t *out, ptrdiff_t out_stride, \ @@ -91,14 +100,26 @@ #undef QPEL +template <class inter_t> +void put_qpel_0_0_fallback_16(inter_t *out, ptrdiff_t out_stride, + const uint16_t *src, ptrdiff_t srcstride, + int nPbW, int nPbH, inter_t* mcbuffer, int bit_depth); + #define QPEL(x,y) void put_qpel_ ## x ## _ ## y ## _fallback_16(int16_t *out, ptrdiff_t out_stride, \ const uint16_t *src, ptrdiff_t srcstride, \ int nPbW, int nPbH, int16_t* mcbuffer, int bit_depth) -QPEL(0,0); QPEL(0,1); QPEL(0,2); QPEL(0,3); +/* */ QPEL(0,1); QPEL(0,2); QPEL(0,3); QPEL(1,0); QPEL(1,1); QPEL(1,2); QPEL(1,3); QPEL(2,0); QPEL(2,1); QPEL(2,2); QPEL(2,3); QPEL(3,0); QPEL(3,1); QPEL(3,2); QPEL(3,3); #undef QPEL +// Same with int32_t intermediates (BitDepth > 12), for all fractional +// positions including full-sample (xFracL == yFracL == 0). +void put_qpel_fallback_16_32(int32_t *out, ptrdiff_t out_stride, + const uint16_t *src, ptrdiff_t srcstride, + int nPbW, int nPbH, int32_t* mcbuffer, + int xFracL, int yFracL, int bit_depth); + #endif
View file
libde265-1.1.2.tar.gz/libde265/fallback.cc -> libde265-1.1.3.tar.gz/libde265/fallback.cc
Changed
@@ -32,16 +32,22 @@ accel->put_weighted_pred_8 = put_weighted_pred_8_fallback; accel->put_weighted_bipred_8 = put_weighted_bipred_8_fallback; - accel->put_weighted_pred_avg_16 = put_weighted_pred_avg_16_fallback; - accel->put_unweighted_pred_16 = put_unweighted_pred_16_fallback; - accel->put_weighted_pred_16 = put_weighted_pred_16_fallback; - accel->put_weighted_bipred_16 = put_weighted_bipred_16_fallback; + accel->put_weighted_pred_avg_16 = put_weighted_pred_avg_16_fallback<int16_t>; + accel->put_unweighted_pred_16 = put_unweighted_pred_16_fallback<int16_t>; + accel->put_weighted_pred_16 = put_weighted_pred_16_fallback<int16_t>; + accel->put_weighted_bipred_16 = put_weighted_bipred_16_fallback<int16_t>; + + // BitDepth > 12: int32_t intermediates + accel->put_weighted_pred_avg_16_32 = put_weighted_pred_avg_16_fallback<int32_t>; + accel->put_unweighted_pred_16_32 = put_unweighted_pred_16_fallback<int32_t>; + accel->put_weighted_pred_16_32 = put_weighted_pred_16_fallback<int32_t>; + accel->put_weighted_bipred_16_32 = put_weighted_bipred_16_fallback<int32_t>; accel->put_hevc_epel_8 = put_epel_8_fallback; - accel->put_hevc_epel_h_8 = put_epel_hv_fallback<uint8_t>; - accel->put_hevc_epel_v_8 = put_epel_hv_fallback<uint8_t>; - accel->put_hevc_epel_hv_8 = put_epel_hv_fallback<uint8_t>; + accel->put_hevc_epel_h_8 = put_epel_hv_fallback<uint8_t,int16_t>; + accel->put_hevc_epel_v_8 = put_epel_hv_fallback<uint8_t,int16_t>; + accel->put_hevc_epel_hv_8 = put_epel_hv_fallback<uint8_t,int16_t>; accel->put_hevc_qpel_800 = put_qpel_0_0_fallback; accel->put_hevc_qpel_801 = put_qpel_0_1_fallback; @@ -60,12 +66,12 @@ accel->put_hevc_qpel_832 = put_qpel_3_2_fallback; accel->put_hevc_qpel_833 = put_qpel_3_3_fallback; - accel->put_hevc_epel_16 = put_epel_16_fallback; - accel->put_hevc_epel_h_16 = put_epel_hv_fallback<uint16_t>; - accel->put_hevc_epel_v_16 = put_epel_hv_fallback<uint16_t>; - accel->put_hevc_epel_hv_16 = put_epel_hv_fallback<uint16_t>; + accel->put_hevc_epel_16 = put_epel_16_fallback<int16_t>; + accel->put_hevc_epel_h_16 = put_epel_hv_fallback<uint16_t,int16_t>; + accel->put_hevc_epel_v_16 = put_epel_hv_fallback<uint16_t,int16_t>; + accel->put_hevc_epel_hv_16 = put_epel_hv_fallback<uint16_t,int16_t>; - accel->put_hevc_qpel_1600 = put_qpel_0_0_fallback_16; + accel->put_hevc_qpel_1600 = put_qpel_0_0_fallback_16<int16_t>; accel->put_hevc_qpel_1601 = put_qpel_0_1_fallback_16; accel->put_hevc_qpel_1602 = put_qpel_0_2_fallback_16; accel->put_hevc_qpel_1603 = put_qpel_0_3_fallback_16; @@ -82,6 +88,14 @@ accel->put_hevc_qpel_1632 = put_qpel_3_2_fallback_16; accel->put_hevc_qpel_1633 = put_qpel_3_3_fallback_16; + // BitDepth > 12: int32_t intermediates + accel->put_hevc_epel_16_32 = put_epel_16_fallback<int32_t>; + accel->put_hevc_epel_h_16_32 = put_epel_hv_fallback<uint16_t,int32_t>; + accel->put_hevc_epel_v_16_32 = put_epel_hv_fallback<uint16_t,int32_t>; + accel->put_hevc_epel_hv_16_32 = put_epel_hv_fallback<uint16_t,int32_t>; + + accel->put_hevc_qpel_16_32 = put_qpel_fallback_16_32; + accel->transform_skip_8 = transform_skip_8_fallback;
View file
libde265-1.1.2.tar.gz/libde265/image.cc -> libde265-1.1.3.tar.gz/libde265/image.cc
Changed
@@ -37,6 +37,8 @@ #ifdef HAVE_SSE4_1 // SSE code processes 128bit per iteration and thus might read more data // than is later actually used. +// NOTE: custom image allocators have to provide this padding too. When increasing +// it, update the de265_image_allocation documentation in de265.h accordingly. #define MEMORY_PADDING 16 #else #define MEMORY_PADDING 0 @@ -511,33 +513,26 @@ assert(bytes_per_pixel == 2); // if we fill the same byte value to all bytes, we can still use memset() - memset(pixelschannel, 0, plane_bytes + MEMORY_PADDING); + memset(pixelschannel, value & 0xFF, plane_bytes + MEMORY_PADDING); } else { assert(bytes_per_pixel == 2); uint16_t v = value; - if (channel==0) { - // copy value into first row - for (int x = 0; x < width; x++) { - *reinterpret_cast<uint16_t*>(&pixelschannel2 * x) = v; - } + // Fill whole rows including the stride padding. This covers every byte of the + // plane, so no part of it is left with whatever the image allocator handed us. - // copy first row into remaining rows - for (int y = 1; y < height; y++) { - memcpy(pixelschannel + y * stride * 2, pixelschannel, chroma_width * 2); - } + const ptrdiff_t row_width = (channel==0 ? stride : chroma_stride); + const int nRows = (channel==0 ? height : chroma_height); + + // copy value into first row + for (ptrdiff_t x = 0; x < row_width; x++) { + *reinterpret_cast<uint16_t*>(&pixelschannel2 * x) = v; } - else { - // copy value into first row - for (int x = 0; x < chroma_width; x++) { - *reinterpret_cast<uint16_t*>(&pixelschannel2 * x) = v; - } - // copy first row into remaining rows - for (int y = 1; y < chroma_height; y++) { - memcpy(pixelschannel + y * chroma_stride * 2, pixelschannel, chroma_width * 2); - } + // copy first row into remaining rows + for (int y = 1; y < nRows; y++) { + memcpy(pixelschannel + y * row_width * 2, pixelschannel, row_width * 2); } #if MEMORY_PADDING > 0
View file
libde265-1.1.2.tar.gz/libde265/image.h -> libde265-1.1.3.tar.gz/libde265/image.h
Changed
@@ -88,7 +88,7 @@ MetaDataArray() = default; ~MetaDataArray() { free(data); } - LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { + nodiscard bool alloc(int w,int h, uint8_t _log2unitSize) { int size = w*h; if (size != data_size) {
View file
libde265-1.1.2.tar.gz/libde265/motion.cc -> libde265-1.1.3.tar.gz/libde265/motion.cc
Changed
@@ -45,11 +45,14 @@ -template <class pixel_t> +// Luma sample interpolation process (8.5.3.3.3.2). +// inter_t is the type of the intermediate prediction samples (see +// generate_inter_prediction_samples_plane below). +template <class pixel_t, class inter_t> void mc_luma(const base_context* ctx, const seq_parameter_set* sps, int mv_x, int mv_y, int xP,int yP, - int16_t* out, int out_stride, + inter_t* out, int out_stride, const pixel_t* ref, ptrdiff_t ref_stride, int nPbW, int nPbH, int bitDepth_L) { @@ -59,16 +62,14 @@ int xIntOffsL = xP + (mv_x>>2); int yIntOffsL = yP + (mv_y>>2); - // luma sample interpolation process (8.5.3.2.2.1) - - //const int shift1 = sps->BitDepth_Y-8; + //const int shift1 = std::min(4, sps->BitDepth_Y-8); //const int shift2 = 6; const int shift3 = std::max(2, 14 - sps->BitDepth_Y); int w = sps->pic_width_in_luma_samples; int h = sps->pic_height_in_luma_samples; - ALIGNED_16(int16_t) mcbufferMAX_CU_SIZE * (MAX_CU_SIZE+7); + ALIGNED_16(inter_t) mcbufferMAX_CU_SIZE * (MAX_CU_SIZE+7); if (xFracL==0 && yFracL==0) { @@ -175,18 +176,17 @@ -template <class pixel_t> +// Chroma sample interpolation process (8.5.3.3.3.3). +template <class pixel_t, class inter_t> void mc_chroma(const base_context* ctx, const seq_parameter_set* sps, int mv_x, int mv_y, int xP,int yP, - int16_t* out, int out_stride, + inter_t* out, int out_stride, const pixel_t* ref, ptrdiff_t ref_stride, int nPbWC, int nPbHC, int bit_depth_C) { - // chroma sample interpolation process (8.5.3.2.2.2) - - //const int shift1 = sps->BitDepth_C-8; + //const int shift1 = std::min(4, sps->BitDepth_C-8); //const int shift2 = 6; const int shift3 = std::max(2, 14 - sps->BitDepth_C); @@ -202,7 +202,7 @@ int xIntOffsC = xP/sps->SubWidthC + (mv_x>>3); int yIntOffsC = yP/sps->SubHeightC + (mv_y>>3); - ALIGNED_32(int16_t mcbufferMAX_CU_SIZE*(MAX_CU_SIZE+7)); + ALIGNED_32(inter_t mcbufferMAX_CU_SIZE*(MAX_CU_SIZE+7)); if (xFracC == 0 && yFracC == 0) { if (xIntOffsC>=0 && nPbWC+xIntOffsC<=wC && @@ -283,7 +283,160 @@ -// 8.5.3.2 +// Fractional sample interpolation (8.5.3.3.3) and weighted sample prediction +// (8.5.3.3.4) for one colour plane. +// +// inter_t is the type of the intermediate prediction samples predSamplesLX. +// The spec keeps them at max(14, BitDepth+2) bits plus the overshoot of the +// interpolation filters, which fits into int16_t only up to +// MC_MAX_BIT_DEPTH_INT16. Above that, int32_t is used (see acceleration.h). +// +// refPicl is NULL when list l is not used or when its reference picture is +// unusable. The caller has already reported the latter; the prediction is then +// filled with mid-grey. +// +// Forced inline: called once per colour plane from a hot loop, and inlining lets +// the compiler set up the prediction sample buffer once per PB instead of once +// per plane. +template <class inter_t> +static LIBDE265_ALWAYS_INLINE void generate_inter_prediction_samples_plane(base_context* ctx, + const slice_segment_header* shdr, + de265_image* img, + int cIdx, + int xP,int yP, + int nCS, int nPbW,int nPbH, + const PBMotion* vi, + const int predFlag2, + const de265_image* const refPic2) +{ + const pic_parameter_set* pps = shdr->pps.get(); + const seq_parameter_set* sps = pps->sps.get(); + + const int bit_depth = sps->get_bit_depth(cIdx); + + const int SubWidthC = (cIdx==0 ? 1 : sps->SubWidthC); + const int SubHeightC = (cIdx==0 ? 1 : sps->SubHeightC); + const int w = nPbW / SubWidthC; + const int h = nPbH / SubHeightC; + + void* pixels = img->get_image_plane_at_pos_any_depth(cIdx, xP/SubWidthC, yP/SubHeightC); + const ptrdiff_t stride = img->get_image_stride(cIdx); + + // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW? + ALIGNED_16(inter_t) predSamples2 /* LX */MAX_CU_SIZE* MAX_CU_SIZE; + + + // --- fractional sample interpolation (8.5.3.3.3) --- + + for (int l=0;l<2;l++) { + if (!predFlagl) continue; + + if (!refPicl) { + // Fill with mid-grey in intermediate precision: (1 << (bit_depth-1)) << shift3. + const inter_t fill = inter_t(1) << (bit_depth-1 + std::max(2, 14-bit_depth)); + + for (int y=0;y<h;y++) + for (int x=0;x<w;x++) + predSamplesly*nCS+x = fill; + + continue; + } + + if (cIdx==0) { + if (img->high_bit_depth(0)) { + mc_luma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, + predSamplesl,nCS, + (const uint16_t*)refPicl->get_image_plane(0), + refPicl->get_luma_stride(), nPbW,nPbH, bit_depth); + } + else { + mc_luma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, + predSamplesl,nCS, + (const uint8_t*)refPicl->get_image_plane(0), + refPicl->get_luma_stride(), nPbW,nPbH, bit_depth); + } + } + else { + if (img->high_bit_depth(cIdx)) { + mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, + predSamplesl,nCS, + (const uint16_t*)refPicl->get_image_plane(cIdx), + refPicl->get_chroma_stride(), w,h, bit_depth); + } + else { + mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, + predSamplesl,nCS, + (const uint8_t*)refPicl->get_image_plane(cIdx), + refPicl->get_chroma_stride(), w,h, bit_depth); + } + } + } + + + // --- weighted sample prediction (8.5.3.3.4) --- + + const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ? + pps->weighted_pred_flag : pps->weighted_bipred_flag); + + // explicit weighted prediction parameters (8.5.3.3.4.3) + + const int shift1 = std::max(2, 14-bit_depth); + const int log2WD = (cIdx==0 ? shdr->luma_log2_weight_denom : shdr->ChromaLog2WeightDenom) + shift1; + const int offsetShift = (cIdx==0 ? sps->WpOffsetBdShiftY : sps->WpOffsetBdShiftC); + + auto weight = &(int l) -> int { + const int refIdx = vi->refIdxl; + return (cIdx==0 ? shdr->LumaWeightlrefIdx : shdr->ChromaWeightlrefIdxcIdx-1); + }; + + auto offset = &(int l) -> int { + const int refIdx = vi->refIdxl; + const int o = (cIdx==0 ? shdr->luma_offsetlrefIdx : shdr->ChromaOffsetlrefIdxcIdx-1); + return o * (1<<offsetShift); + }; + + + if (predFlag0 && predFlag1) { + if (!weightedPredFlag) { + ctx->acceleration.put_weighted_pred_avg(pixels, stride, + predSamples0, predSamples1, nCS, + w,h, bit_depth); + } + else { + logtrace(LogMotion,"weighted-BI-0 %d %d %d %d %dx%d\n", vi->refIdx0, log2WD-6,weight(0),offset(0),w,h); + logtrace(LogMotion,"weighted-BI-1 %d %d %d %d %dx%d\n", vi->refIdx1, log2WD-6,weight(1),offset(1),w,h); + + ctx->acceleration.put_weighted_bipred(pixels, stride, + predSamples0, predSamples1, nCS, + w,h, + weight(0),offset(0), + weight(1),offset(1), + log2WD, bit_depth); + } + } + else { + const int l = (predFlag0 ? 0 : 1); // the caller ensures that one list is used + + if (!weightedPredFlag) { + ctx->acceleration.put_unweighted_pred(pixels, stride, + predSamplesl, nCS, + w,h, bit_depth); + } + else { + logtrace(LogMotion,"weighted-L%d %d %d %d %d %dx%d\n", l, vi->refIdxl, log2WD-6,weight(l),offset(l),w,h); + + ctx->acceleration.put_weighted_pred(pixels, stride, + predSamplesl, nCS, + w,h, + weight(l),offset(l), + log2WD, bit_depth); + } + } +} + + + +// Decoding process for inter prediction samples (8.5.3.3). // NOTE: for full-pel shifts, we can introduce a fast path, simply copying without shifts void generate_inter_prediction_samples(base_context* ctx, const slice_segment_header* shdr, @@ -293,11 +446,8 @@ int nCS, int nPbW,int nPbH, const PBMotion* vi) { - int xP = xC+xB; - int yP = yC+yB; - - void* pixels3; - int stride3; + const int xP = xC+xB; + const int yP = yC+yB; const pic_parameter_set* pps = shdr->pps.get(); const seq_parameter_set* sps = pps->sps.get(); @@ -315,37 +465,19 @@ return; } - const int SubWidthC = sps->SubWidthC; - const int SubHeightC = sps->SubHeightC; - - pixels0 = img->get_image_plane_at_pos_any_depth(0,xP,yP); - stride0 = img->get_image_stride(0); - - pixels1 = img->get_image_plane_at_pos_any_depth(1,xP/SubWidthC,yP/SubHeightC); - stride1 = img->get_image_stride(1); - - pixels2 = img->get_image_plane_at_pos_any_depth(2,xP/SubWidthC,yP/SubHeightC); - stride2 = img->get_image_stride(2); - - - ALIGNED_16(int16_t) predSamplesL 2 /* LX */MAX_CU_SIZE* MAX_CU_SIZE; - ALIGNED_16(int16_t) predSamplesC2 /* chroma */ 2 /* LX */MAX_CU_SIZE* MAX_CU_SIZE; - - //int xP = xC+xB; - //int yP = yC+yB; int predFlag2; predFlag0 = vi->predFlag0; predFlag1 = vi->predFlag1; - const int bit_depth_L = sps->BitDepth_Y; - const int bit_depth_C = sps->BitDepth_C; + // Some encoders use bi-prediction with two identical MVs onto the same picture. + // Identify this case and use only one MV. This is not possible with explicit + // weighted prediction, where the two lists may have different weights/offsets. - // Some encoders use bi-prediction with two similar MVs. - // Identify this case and use only one MV. + const bool weightedPredFlag = (shdr->slice_type == SLICE_TYPE_P ? + pps->weighted_pred_flag : pps->weighted_bipred_flag); - // do this only without weighted prediction, because the weights/offsets may be different - if (pps->weighted_pred_flag==0) { + if (!weightedPredFlag) { if (predFlag0 && predFlag1) { if (vi->mv0.x == vi->mv1.x && vi->mv0.y == vi->mv1.y && @@ -356,379 +488,75 @@ } } + logtrace(LogMotion,"predFlags (modified): %d %d\n", predFlag0, predFlag1); - // Fill prediction samples with mid-grey in intermediate precision. - // Used on error paths where the reference picture is unavailable or mismatched. - auto fill_pred_samples = &(int l) { - const int16_t fill = 1 << 13; // mid-grey: (1 << (bd-1)) << (14-bd) for any bd - for (int y = 0; y < nPbH; y++) - for (int x = 0; x < nPbW; x++) - predSamplesLly * nCS + x = fill; - if (img->get_chroma_format() != de265_chroma_mono) { - int cW = nPbW / SubWidthC; - int cH = nPbH / SubHeightC; - for (int y = 0; y < cH; y++) - for (int x = 0; x < cW; x++) { - predSamplesC0ly * nCS + x = fill; - predSamplesC1ly * nCS + x = fill; - } - } - }; - - for (int l=0;l<2;l++) { - if (predFlagl) { - // 8.5.3.2.1 - - const de265_image* refPic = ctx->get_image(shdr->RefPicListlvi->refIdxl); - - logtrace(LogMotion, "refIdx: %d -> dpb%d\n", vi->refIdxl, shdr->RefPicListlvi->refIdxl); - - if (!refPic || refPic->PicState == UnusedForReference) { - img->integrity = INTEGRITY_DECODING_ERRORS; - ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false); - fill_pred_samples(l); - } - else if (refPic->get_width(0) != sps->pic_width_in_luma_samples || - refPic->get_height(0) != sps->pic_height_in_luma_samples || - img->get_chroma_format() != refPic->get_chroma_format()) { - img->integrity = INTEGRITY_DECODING_ERRORS; - ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_SIZE_DOES_NOT_MATCH_SPS, false); - fill_pred_samples(l); - } - else if (img->get_bit_depth(0) != refPic->get_bit_depth(0) || - img->get_bit_depth(1) != refPic->get_bit_depth(1)) { - img->integrity = INTEGRITY_DECODING_ERRORS; - ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_BIT_DEPTH_DOES_NOT_MATCH, false); - fill_pred_samples(l); - } - else if (img->get_chroma_format() != refPic->get_chroma_format()) { - img->integrity = INTEGRITY_DECODING_ERRORS; - ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_CHROMA_FORMAT_DOES_NOT_MATCH, false); - fill_pred_samples(l); - } - else { - // 8.5.3.2.2 - - logtrace(LogMotion,"do MC: L%d,MV=%d;%d RefPOC=%d\n", - l,vi->mvl.x,vi->mvl.y,refPic->PicOrderCntVal); - - - // TODO: must predSamples stride really be nCS or can it be something smaller like nPbW? + if (!predFlag0 && !predFlag1) { + // TODO: check why it can actually happen that both predFlags are false. + // For now, we ignore this and continue decoding. - if (img->high_bit_depth(0)) { - mc_luma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, - predSamplesLl,nCS, - (const uint16_t*)refPic->get_image_plane(0), - refPic->get_luma_stride(), nPbW,nPbH, bit_depth_L); - } - else { - mc_luma(ctx, sps, vi->mvl.x, vi->mvl.y, xP,yP, - predSamplesLl,nCS, - (const uint8_t*)refPic->get_image_plane(0), - refPic->get_luma_stride(), nPbW,nPbH, bit_depth_L); - } - - if (img->get_chroma_format() != de265_chroma_mono) { - if (img->high_bit_depth(1)) { - mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP, yP, - predSamplesC0l, nCS, (const uint16_t*) refPic->get_image_plane(1), - refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP, yP, - predSamplesC1l, nCS, (const uint16_t*) refPic->get_image_plane(2), - refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - } - else { - mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP, yP, - predSamplesC0l, nCS, (const uint8_t*) refPic->get_image_plane(1), - refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - mc_chroma(ctx, sps, vi->mvl.x, vi->mvl.y, xP, yP, - predSamplesC1l, nCS, (const uint8_t*) refPic->get_image_plane(2), - refPic->get_chroma_stride(), nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - } - } - } - } + ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false); + img->integrity = INTEGRITY_DECODING_ERRORS; + return; } - // weighted sample prediction (8.5.3.2.3) + // --- reference picture selection (8.5.3.3.2) --- - const int shift1_L = std::max(2,14-sps->BitDepth_Y); - const int offset_shift1_L = img->get_sps().WpOffsetBdShiftY; - const int shift1_C = std::max(2,14-sps->BitDepth_C); - const int offset_shift1_C = img->get_sps().WpOffsetBdShiftC; + // refPicl stays NULL when the reference picture cannot be used. - /* - const int shift1_L = 14-img->sps.BitDepth_Y; - const int offset_shift1_L = img->sps.BitDepth_Y-8; - const int shift1_C = 14-img->sps.BitDepth_C; - const int offset_shift1_C = img->sps.BitDepth_C-8; - */ + const de265_image* refPic2 = { nullptr, nullptr }; - /* - if (0) - printf("%d/%d %d/%d %d/%d %d/%d\n", - shift1_L, - Nshift1_L, - offset_shift1_L, - Noffset_shift1_L, - shift1_C, - Nshift1_C, - offset_shift1_C, - Noffset_shift1_C); - - assert(shift1_L== - Nshift1_L); - assert(offset_shift1_L== - Noffset_shift1_L); - assert(shift1_C== - Nshift1_C); - assert(offset_shift1_C== - Noffset_shift1_C); - */ + for (int l=0;l<2;l++) { + if (!predFlagl) continue; + const de265_image* ref = ctx->get_image(shdr->RefPicListlvi->refIdxl); - logtrace(LogMotion,"predFlags (modified): %d %d\n", predFlag0, predFlag1); + logtrace(LogMotion, "refIdx: %d -> dpb%d\n", vi->refIdxl, shdr->RefPicListlvi->refIdxl); - if (shdr->slice_type == SLICE_TYPE_P) { - if (pps->weighted_pred_flag==0) { - if (predFlag0==1 && predFlag1==0) { - ctx->acceleration.put_unweighted_pred(pixels0, stride0, - predSamplesL0,nCS, nPbW,nPbH, bit_depth_L); - - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_unweighted_pred(pixels1, stride1, - predSamplesC00, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - ctx->acceleration.put_unweighted_pred(pixels2, stride2, - predSamplesC10, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - } - } - else { - ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false); - img->integrity = INTEGRITY_DECODING_ERRORS; - } + if (!ref || ref->PicState == UnusedForReference) { + img->integrity = INTEGRITY_DECODING_ERRORS; + ctx->add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false); } - else { - // weighted prediction - - if (predFlag0==1 && predFlag1==0) { - - int refIdx0 = vi->refIdx0; - - int luma_log2WD = shdr->luma_log2_weight_denom + shift1_L; - int chroma_log2WD = shdr->ChromaLog2WeightDenom + shift1_C; - - int luma_w0 = shdr->LumaWeight0refIdx0; - int luma_o0 = shdr->luma_offset0refIdx0 * (1<<(offset_shift1_L)); - - int chroma0_w0 = shdr->ChromaWeight0refIdx00; - int chroma0_o0 = shdr->ChromaOffset0refIdx00 * (1<<(offset_shift1_C)); - int chroma1_w0 = shdr->ChromaWeight0refIdx01; - int chroma1_o0 = shdr->ChromaOffset0refIdx01 * (1<<(offset_shift1_C)); - - logtrace(LogMotion,"weighted-0 %d %d %d %d %dx%d\n", refIdx0, luma_log2WD-6,luma_w0,luma_o0,nPbW,nPbH); - - ctx->acceleration.put_weighted_pred(pixels0, stride0, - predSamplesL0,nCS, nPbW,nPbH, - luma_w0, luma_o0, luma_log2WD, bit_depth_L); - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_weighted_pred(pixels1, stride1, - predSamplesC00, nCS, nPbW / SubWidthC, nPbH / SubHeightC, - chroma0_w0, chroma0_o0, chroma_log2WD, bit_depth_C); - ctx->acceleration.put_weighted_pred(pixels2, stride2, - predSamplesC10, nCS, nPbW / SubWidthC, nPbH / SubHeightC, - chroma1_w0, chroma1_o0, chroma_log2WD, bit_depth_C); - } - } - else { - ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false); - img->integrity = INTEGRITY_DECODING_ERRORS; - } + else if (ref->get_width(0) != sps->pic_width_in_luma_samples || + ref->get_height(0) != sps->pic_height_in_luma_samples) { + img->integrity = INTEGRITY_DECODING_ERRORS; + ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_SIZE_DOES_NOT_MATCH_SPS, false); } - } - else { - assert(shdr->slice_type == SLICE_TYPE_B); - - if (predFlag0==1 && predFlag1==1) { - if (pps->weighted_bipred_flag==0) { - //const int shift2 = 15-8; // TODO: real bit depth - //const int offset2 = 1<<(shift2-1); - - int16_t* in0 = predSamplesL0; - int16_t* in1 = predSamplesL1; - - ctx->acceleration.put_weighted_pred_avg(pixels0, stride0, - in0,in1, nCS, nPbW, nPbH, bit_depth_L); - - int16_t* in00 = predSamplesC00; - int16_t* in01 = predSamplesC01; - int16_t* in10 = predSamplesC10; - int16_t* in11 = predSamplesC11; - - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_weighted_pred_avg(pixels1, stride1, - in00, in01, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - ctx->acceleration.put_weighted_pred_avg(pixels2, stride2, - in10, in11, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - } - } - else { - // weighted prediction - - int refIdx0 = vi->refIdx0; - int refIdx1 = vi->refIdx1; - - int luma_log2WD = shdr->luma_log2_weight_denom + shift1_L; - int chroma_log2WD = shdr->ChromaLog2WeightDenom + shift1_C; - - int luma_w0 = shdr->LumaWeight0refIdx0; - int luma_o0 = shdr->luma_offset0refIdx0 * (1<<(offset_shift1_L)); - int luma_w1 = shdr->LumaWeight1refIdx1; - int luma_o1 = shdr->luma_offset1refIdx1 * (1<<(offset_shift1_L)); - - int chroma0_w0 = shdr->ChromaWeight0refIdx00; - int chroma0_o0 = shdr->ChromaOffset0refIdx00 * (1<<(offset_shift1_C)); - int chroma1_w0 = shdr->ChromaWeight0refIdx01; - int chroma1_o0 = shdr->ChromaOffset0refIdx01 * (1<<(offset_shift1_C)); - int chroma0_w1 = shdr->ChromaWeight1refIdx10; - int chroma0_o1 = shdr->ChromaOffset1refIdx10 * (1<<(offset_shift1_C)); - int chroma1_w1 = shdr->ChromaWeight1refIdx11; - int chroma1_o1 = shdr->ChromaOffset1refIdx11 * (1<<(offset_shift1_C)); - - logtrace(LogMotion,"weighted-BI-0 %d %d %d %d %dx%d\n", refIdx0, luma_log2WD-6,luma_w0,luma_o0,nPbW,nPbH); - logtrace(LogMotion,"weighted-BI-1 %d %d %d %d %dx%d\n", refIdx1, luma_log2WD-6,luma_w1,luma_o1,nPbW,nPbH); - - int16_t* in0 = predSamplesL0; - int16_t* in1 = predSamplesL1; - - ctx->acceleration.put_weighted_bipred(pixels0, stride0, - in0,in1, nCS, nPbW, nPbH, - luma_w0,luma_o0, - luma_w1,luma_o1, - luma_log2WD, bit_depth_L); - - int16_t* in00 = predSamplesC00; - int16_t* in01 = predSamplesC01; - int16_t* in10 = predSamplesC10; - int16_t* in11 = predSamplesC11; - - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_weighted_bipred(pixels1, stride1, - in00, in01, nCS, nPbW / SubWidthC, nPbH / SubHeightC, - chroma0_w0, chroma0_o0, - chroma0_w1, chroma0_o1, - chroma_log2WD, bit_depth_C); - ctx->acceleration.put_weighted_bipred(pixels2, stride2, - in10, in11, nCS, nPbW / SubWidthC, nPbH / SubHeightC, - chroma1_w0, chroma1_o0, - chroma1_w1, chroma1_o1, - chroma_log2WD, bit_depth_C); - } - } + else if (img->get_bit_depth(0) != ref->get_bit_depth(0) || + img->get_bit_depth(1) != ref->get_bit_depth(1)) { + img->integrity = INTEGRITY_DECODING_ERRORS; + ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_BIT_DEPTH_DOES_NOT_MATCH, false); } - else if (predFlag0==1 || predFlag1==1) { - int l = predFlag0 ? 0 : 1; - - if (pps->weighted_bipred_flag==0) { - ctx->acceleration.put_unweighted_pred(pixels0, stride0, - predSamplesLl,nCS, nPbW,nPbH, bit_depth_L); - - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_unweighted_pred(pixels1, stride1, - predSamplesC0l, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - ctx->acceleration.put_unweighted_pred(pixels2, stride2, - predSamplesC1l, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, bit_depth_C); - } - } - else { - int refIdx = vi->refIdxl; - - int luma_log2WD = shdr->luma_log2_weight_denom + shift1_L; - int chroma_log2WD = shdr->ChromaLog2WeightDenom + shift1_C; - - int luma_w = shdr->LumaWeightlrefIdx; - int luma_o = shdr->luma_offsetlrefIdx * (1<<(offset_shift1_L)); - - int chroma0_w = shdr->ChromaWeightlrefIdx0; - int chroma0_o = shdr->ChromaOffsetlrefIdx0 * (1<<(offset_shift1_C)); - int chroma1_w = shdr->ChromaWeightlrefIdx1; - int chroma1_o = shdr->ChromaOffsetlrefIdx1 * (1<<(offset_shift1_C)); - - logtrace(LogMotion,"weighted-B-L%d %d %d %d %d %dx%d\n", l, refIdx, luma_log2WD-6,luma_w,luma_o,nPbW,nPbH); - - ctx->acceleration.put_weighted_pred(pixels0, stride0, - predSamplesLl,nCS, nPbW,nPbH, - luma_w, luma_o, luma_log2WD, bit_depth_L); - - if (img->get_chroma_format() != de265_chroma_mono) { - ctx->acceleration.put_weighted_pred(pixels1, stride1, - predSamplesC0l, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, - chroma0_w, chroma0_o, chroma_log2WD, bit_depth_C); - ctx->acceleration.put_weighted_pred(pixels2, stride2, - predSamplesC1l, nCS, - nPbW / SubWidthC, nPbH / SubHeightC, - chroma1_w, chroma1_o, chroma_log2WD, bit_depth_C); - } - } + else if (img->get_chroma_format() != ref->get_chroma_format()) { + img->integrity = INTEGRITY_DECODING_ERRORS; + ctx->add_warning(DE265_WARNING_REFERENCE_IMAGE_CHROMA_FORMAT_DOES_NOT_MATCH, false); } else { - // TODO: check why it can actually happen that both predFlags are false. - // For now, we ignore this and continue decoding. + logtrace(LogMotion,"do MC: L%d,MV=%d;%d RefPOC=%d\n", + l,vi->mvl.x,vi->mvl.y,ref->PicOrderCntVal); - ctx->add_warning(DE265_WARNING_BOTH_PREDFLAGS_ZERO, false); - img->integrity = INTEGRITY_DECODING_ERRORS; + refPicl = ref; } } -#if defined(DE265_LOG_TRACE) && 0 - logtrace(LogTransform,"MC pixels (luma), position %d %d:\n", xP,yP); - - for (int y=0;y<nPbH;y++) { - logtrace(LogTransform,"MC-y-%d-%d ",xP,yP+y); - for (int x=0;x<nPbW;x++) { - logtrace(LogTransform,"*%02x ", pixels0x+y*stride0); - } - - logtrace(LogTransform,"*\n"); - } + // --- prediction, per colour plane --- + // Up to MC_MAX_BIT_DEPTH_INT16, the intermediate prediction samples fit + // into int16_t. Above that, int32_t is needed. - logtrace(LogTransform,"MC pixels (chroma cb), position %d %d:\n", xP/2,yP/2); + const int nPlanes = (img->get_chroma_format() == de265_chroma_mono ? 1 : 3); - for (int y=0;y<nPbH/2;y++) { - logtrace(LogTransform,"MC-cb-%d-%d ",xP/2,yP/2+y); - - for (int x=0;x<nPbW/2;x++) { - logtrace(LogTransform,"*%02x ", pixels1x+y*stride1); + for (int cIdx=0;cIdx<nPlanes;cIdx++) { + if (sps->get_bit_depth(cIdx) <= MC_MAX_BIT_DEPTH_INT16) { + generate_inter_prediction_samples_plane<int16_t>(ctx,shdr,img, cIdx, xP,yP, nCS,nPbW,nPbH, vi, predFlag, refPic); } - - logtrace(LogTransform,"*\n"); - } - - - logtrace(LogTransform,"MC pixels (chroma cr), position %d %d:\n", xP/2,yP/2); - - for (int y=0;y<nPbH/2;y++) { - logtrace(LogTransform,"MC-cr-%d-%d ",xP/2,yP/2+y); - - for (int x=0;x<nPbW/2;x++) { - logtrace(LogTransform,"*%02x ", pixels2x+y*stride2); + else { + generate_inter_prediction_samples_plane<int32_t>(ctx,shdr,img, cIdx, xP,yP, nCS,nPbW,nPbH, vi, predFlag, refPic); } - - logtrace(LogTransform,"*\n"); } -#endif } - #ifdef DE265_LOG_TRACE void logmvcand(const PBMotion& p) {
View file
libde265-1.1.2.tar.gz/libde265/nal-parser.cc -> libde265-1.1.3.tar.gz/libde265/nal-parser.cc
Changed
@@ -26,35 +26,19 @@ #include <stdio.h> #include <stdint.h> #include <limits.h> +#include <utility> #ifdef HAVE_CONFIG_H #include "config.h" #endif -NAL_unit::NAL_unit() - : skipped_bytes(DE265_SKIPPED_BYTES_INITIAL_SIZE) -{ -} - NAL_unit::~NAL_unit() { free(nal_data); } -void NAL_unit::clear() -{ - header = nal_header(); - pts = 0; - user_data = nullptr; - - // set size to zero but keep memory - data_size = 0; - - skipped_bytes.clear(); -} - -LIBDE265_CHECK_RESULT bool NAL_unit::resize(int new_size) +nodiscard bool NAL_unit::resize(int new_size) { if (capacity < new_size) { // Grow the buffer geometrically (1.5x) rather than to the exact requested @@ -87,7 +71,7 @@ return true; } -LIBDE265_CHECK_RESULT bool NAL_unit::append(const unsigned char* in_data, int n) +nodiscard bool NAL_unit::append(const unsigned char* in_data, int n) { if (!resize(data_size + n)) { return false; @@ -99,7 +83,7 @@ return true; } -bool LIBDE265_CHECK_RESULT NAL_unit::set_data(const unsigned char* in_data, int n) +nodiscard bool NAL_unit::set_data(const unsigned char* in_data, int n) { if (!resize(n)) { return false; @@ -174,73 +158,39 @@ NAL_Parser::~NAL_Parser() { - // --- free NAL queues --- - - // empty NAL queue - - NAL_unit* nal; - while ( (nal = pop_from_NAL_queue()) ) { - free_NAL_unit(nal); - } - - // free the pending input NAL - - if (pending_input_NAL != nullptr) { - free_NAL_unit(pending_input_NAL); - } - - // free all NALs in free-list - - for (size_t i=0;i<NAL_free_list.size();i++) { - delete NAL_free_listi; - } + // The NAL queue and the pending input NAL hold owning unique_ptrs, so their + // contents are released automatically. Nothing to do. } -LIBDE265_CHECK_RESULT NAL_unit* NAL_Parser::alloc_NAL_unit(int size) +nodiscard std::unique_ptr<NAL_unit> NAL_Parser::alloc_NAL_unit(int size) { - NAL_unit* nal; - - // --- get NAL-unit object --- + // A freshly constructed NAL_unit is already in the cleared state (empty + // buffer, empty skipped-byte list), so no clear() is needed here. + auto nal = std::make_unique<NAL_unit>(); - if (NAL_free_list.size() > 0) { - nal = NAL_free_list.back(); - NAL_free_list.pop_back(); - } - else { - nal = new NAL_unit; - } - - nal->clear(); if (!nal->resize(size)) { - free_NAL_unit(nal); - return nullptr; + return nullptr; // 'nal' is deleted as it goes out of scope } return nal; } -void NAL_Parser::free_NAL_unit(NAL_unit* nal) +void NAL_Parser::free_NAL_unit(std::unique_ptr<NAL_unit> /*nal*/) { - if (nal == nullptr) { - // Allow calling with nullptr just like regular "free()" - return; - } - if (NAL_free_list.size() < DE265_NAL_FREE_LIST_SIZE) { - NAL_free_list.push_back(nal); - } - else { - delete nal; - } + // Releasing a NAL is just destroying it: ownership is moved in by value, so the + // NAL is deleted when the argument goes out of scope here (a moved-from / null + // argument is a harmless no-op). Kept as a named operation so call sites read as + // an explicit release, and because it makes a double release impossible to express. } -NAL_unit* NAL_Parser::pop_from_NAL_queue() +std::unique_ptr<NAL_unit> NAL_Parser::pop_from_NAL_queue() { if (NAL_queue.empty()) { return nullptr; } else { - NAL_unit* nal = NAL_queue.front(); + std::unique_ptr<NAL_unit> nal = std::move(NAL_queue.front()); NAL_queue.pop(); nBytes_in_NAL_queue -= nal->size(); @@ -249,10 +199,10 @@ } } -void NAL_Parser::push_to_NAL_queue(NAL_unit* nal) +void NAL_Parser::push_to_NAL_queue(std::unique_ptr<NAL_unit> nal) { - NAL_queue.push(nal); nBytes_in_NAL_queue += nal->size(); + NAL_queue.push(std::move(nal)); } de265_error NAL_Parser::push_data(const unsigned char* data, int len, @@ -269,7 +219,8 @@ pending_input_NAL->user_data = user_data; } - NAL_unit* nal = pending_input_NAL; // shortcut + // Raw working pointer for byte access; ownership stays in pending_input_NAL. + NAL_unit* nal = pending_input_NAL.get(); // shortcut // Resize output buffer so that complete input would fit. // We add 3, because in the worst case 3 extra bytes are created for an input byte. @@ -341,16 +292,15 @@ // enforce the maximum NAL size: drop an oversized NAL and resync if (!nal_size_within_limit(out - nal->data())) { - free_NAL_unit(pending_input_NAL); - pending_input_NAL = nullptr; + free_NAL_unit(std::move(pending_input_NAL)); input_push_state = 0; return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT; } nal->set_size(out - nal->data());; - // push this NAL decoder queue - push_to_NAL_queue(nal); + // push this completed NAL onto the decoder queue (transfers ownership) + push_to_NAL_queue(std::move(pending_input_NAL)); // initialize new, empty NAL unit @@ -361,7 +311,7 @@ } pending_input_NAL->pts = pts; pending_input_NAL->user_data = user_data; - nal = pending_input_NAL; + nal = pending_input_NAL.get(); out = nal->data(); input_push_state=3; @@ -387,8 +337,7 @@ // reaching a start code. The oversized pending NAL is dropped and the parser // resyncs at the next start code. if (!nal_size_within_limit(nal->size())) { - free_NAL_unit(pending_input_NAL); - pending_input_NAL = nullptr; + free_NAL_unit(std::move(pending_input_NAL)); input_push_state = 0; return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT; } @@ -419,9 +368,9 @@ return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT; } - NAL_unit* nal = alloc_NAL_unit(len); + std::unique_ptr<NAL_unit> nal = alloc_NAL_unit(len); if (nal == nullptr || !nal->set_data(data, len)) { - free_NAL_unit(nal); + free_NAL_unit(std::move(nal)); return DE265_ERROR_OUT_OF_MEMORY; } nal->pts = pts; @@ -429,7 +378,7 @@ nal->remove_stuffing_bytes(); - push_to_NAL_queue(nal); + push_to_NAL_queue(std::move(nal)); return DE265_OK; } @@ -438,7 +387,7 @@ de265_error NAL_Parser::flush_data() { if (pending_input_NAL) { - NAL_unit* nal = pending_input_NAL; + NAL_unit* nal = pending_input_NAL.get(); uint8_t null2 = { 0,0 }; // append bytes that are implied by the push state @@ -458,8 +407,7 @@ // only push the NAL if it contains at least the NAL header if (input_push_state>=5) { - push_to_NAL_queue(nal); - pending_input_NAL = nullptr; + push_to_NAL_queue(std::move(pending_input_NAL)); } input_push_state = 0; @@ -474,13 +422,12 @@ // --- remove pending input data --- if (pending_input_NAL) { - free_NAL_unit(pending_input_NAL); - pending_input_NAL = nullptr; + free_NAL_unit(std::move(pending_input_NAL)); } for (;;) { - NAL_unit* nal = pop_from_NAL_queue(); - if (nal) { free_NAL_unit(nal); } + std::unique_ptr<NAL_unit> nal = pop_from_NAL_queue(); + if (nal) { free_NAL_unit(std::move(nal)); } else break; }
View file
libde265-1.1.2.tar.gz/libde265/nal-parser.h -> libde265-1.1.3.tar.gz/libde265/nal-parser.h
Changed
@@ -29,14 +29,12 @@ #include <vector> #include <queue> - -constexpr int DE265_NAL_FREE_LIST_SIZE = 16; -constexpr int DE265_SKIPPED_BYTES_INITIAL_SIZE = 16; +#include <memory> class NAL_unit { public: - NAL_unit(); + NAL_unit() = default; ~NAL_unit(); nal_header header; @@ -45,13 +43,11 @@ void* user_data = nullptr; - void clear(); - // --- rbsp data --- - LIBDE265_CHECK_RESULT bool resize(int new_size); - LIBDE265_CHECK_RESULT bool append(const unsigned char* data, int n); - LIBDE265_CHECK_RESULT bool set_data(const unsigned char* data, int n); + nodiscard bool resize(int new_size); + nodiscard bool append(const unsigned char* data, int n); + nodiscard bool set_data(const unsigned char* data, int n); int size() const { return data_size; } void set_size(int s) { data_size=s; } @@ -101,7 +97,7 @@ de265_error push_NAL(const unsigned char* data, int len, de265_PTS pts, void* user_data = nullptr); - NAL_unit* pop_from_NAL_queue(); + std::unique_ptr<NAL_unit> pop_from_NAL_queue(); de265_error flush_data(); void mark_end_of_stream() { end_of_stream=true; } void mark_end_of_frame() { end_of_frame=true; } @@ -123,7 +119,11 @@ return NAL_queue.size(); } - void free_NAL_unit(NAL_unit*); + // Release a NAL. Takes ownership by value, so a move transfers the object here + // and leaves the caller holding nullptr; a redundant release therefore passes + // nullptr and is a harmless no-op, which is what makes a double release + // impossible to express. + void free_NAL_unit(std::unique_ptr<NAL_unit> nal); int get_NAL_queue_length() const { return NAL_queue.size(); } @@ -137,17 +137,17 @@ bool end_of_frame = false; // data in pending_input_data is end of frame int input_push_state = 0; - NAL_unit* pending_input_NAL = nullptr; + std::unique_ptr<NAL_unit> pending_input_NAL; const de265_security_limits* m_security_limits = nullptr; // NAL level - std::queue<NAL_unit*> NAL_queue; // enqueued NALs have suffing bytes removed + std::queue<std::unique_ptr<NAL_unit>> NAL_queue; // enqueued NALs have suffing bytes removed int nBytes_in_NAL_queue = 0; // data bytes currently in NAL_queue - void push_to_NAL_queue(NAL_unit*); + void push_to_NAL_queue(std::unique_ptr<NAL_unit>); // Returns true if a NAL unit of the given size is within the configured // security limit (or if no limit is set). @@ -158,11 +158,7 @@ } - // pool of unused NAL memory - - std::vector<NAL_unit*> NAL_free_list; // maximum size: DE265_NAL_FREE_LIST_SIZE - - LIBDE265_CHECK_RESULT NAL_unit* alloc_NAL_unit(int size); + nodiscard std::unique_ptr<NAL_unit> alloc_NAL_unit(int size); };
View file
libde265-1.1.2.tar.gz/libde265/pps.cc -> libde265-1.1.3.tar.gz/libde265/pps.cc
Changed
@@ -55,12 +55,26 @@ if (pps->transform_skip_enabled_flag) { uvlc = br->get_uvlc(); - if (uvlc == UVLC_ERROR || - uvlc > static_cast<uint32_t>(sps->Log2MaxTrafoSize) - 2) { + if (uvlc == UVLC_ERROR) { ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false); return false; } + // The standard requires log2_max_transform_skip_block_size_minus2 <= + // Log2MaxTrafoSize-2, but real-world RExt streams (e.g. the conformance + // stream PERSIST_RPARAM_A_RExt_Sony_2) code a larger value. This field + // only gates whether transform_skip_flag may be present for a TU of a + // given size (log2TrafoSize <= Log2MaxTransformSkipSize); since + // log2TrafoSize can never exceed Log2MaxTrafoSize, clamping to the + // maximum in-range value reproduces the same "always present" decoding + // behavior as any larger out-of-range value, so it is safe to clamp + // instead of rejecting the whole PPS. + uint32_t maxAllowed = static_cast<uint32_t>(sps->Log2MaxTrafoSize) - 2; + if (uvlc > maxAllowed) { + ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false); + uvlc = maxAllowed; + } + log2_max_transform_skip_block_size = uvlc+2; } @@ -522,12 +536,21 @@ } } - // Multilayer extension and the 6 reserved extension bits would carry - // additional payload that we do not parse. Reject the stream. - if (pps_multilayer_extension_flag || pps_extension_6bits) { + // The reserved extension bits could carry a 3D/SCC PPS extension whose + // payload changes base-layer decoding (e.g. SCC palette / adaptive + // colour transform). We do not parse it, so reject the stream. + if (pps_extension_6bits) { ctx->add_warning(DE265_ERROR_NOT_IMPLEMENTED_YET, false); return false; } + + // The multilayer extension only describes enhancement layers appended + // at the end of the PPS RBSP; skipping its payload does not affect + // base-layer decoding or the parsing of subsequent NAL units, so we + // just warn and continue decoding the base layer. + if (pps_multilayer_extension_flag) { + ctx->add_warning(DE265_ERROR_NOT_IMPLEMENTED_YET, false); + } }
View file
libde265-1.1.2.tar.gz/libde265/slice.cc -> libde265-1.1.3.tar.gz/libde265/slice.cc
Changed
@@ -3266,11 +3266,22 @@ c1 = 1; + /* Whether this sub-block codes any escape data, i.e. any coeff_abs_level_remaining. + Only used for cabac_bypass_alignment_enabled_flag (see below). */ + + bool escapeDataPresent = false; + + // --- decode greater-1 flags --- int newLastGreater1ScanPos = -1; int lastGreater1Coefficient = std::min(8, nCoefficients); + + // significant coefficients past the first eight carry no greater-1 flag and are escape coded + if (nCoefficients > 8) { + escapeDataPresent = true; + } for (int c = 0; c < lastGreater1Coefficient; c++) { int greater1_flag = decode_coeff_abs_level_greater1(tctx, cIdx, i, @@ -3289,6 +3300,9 @@ if (newLastGreater1ScanPos == -1) { newLastGreater1ScanPos = c; } + else { + escapeDataPresent = true; + } } else { coeff_has_max_base_levelc = 0; @@ -3309,6 +3323,10 @@ int flag = decode_coeff_abs_level_greater2(tctx, cIdx, lastInvocation_ctxSet); coeff_valuenewLastGreater1ScanPos += flag; coeff_has_max_base_levelnewLastGreater1ScanPos = flag; + + if (flag) { + escapeDataPresent = true; + } } @@ -3335,6 +3353,14 @@ } + /* (9.3.4.3.6) Align the CABAC engine before the bypass-coded sign flags and + remaining levels of a sub-block that carries escape data. No context-coded bin + follows until the end of the sub-block, so aligning once here covers both. */ + + if (sps.range_extension.cabac_bypass_alignment_enabled_flag && escapeDataPresent) { + tctx->cabac_decoder.align_bypass(); + } + for (int n = 0; n < nCoefficients - 1; n++) { coeff_signn = tctx->cabac_decoder.decode_bypass(); logtrace(LogSlice, "sign%d = %d\n", n, coeff_signn);
View file
libde265-1.1.2.tar.gz/libde265/transform.cc -> libde265-1.1.3.tar.gz/libde265/transform.cc
Changed
@@ -245,18 +245,32 @@ { const int BitDepthC = tctx->img->get_sps().BitDepth_C; const int BitDepthY = tctx->img->get_sps().BitDepth_Y; + const int ResScaleVal = tctx->ResScaleVal; + + /* (8.6.6): rxy += ( ResScaleVal * ( ( rYxy << BitDepthC ) >> BitDepthY ) ) >> 3 + Both shifts operate on a signed value, so together they are a single signed rescaling + by (BitDepthC - BitDepthY). It must not be evaluated on an unsigned type: the right + shift would then be logical and turn every negative luma residual into a large + positive value. Shifting left is expressed as a multiplication because shifting a + negative value left is undefined behaviour before C++20. + */ - for (int y=0;y<nT;y++) - for (int x=0;x<nT;x++) { - /* TODO: the most usual case is definitely BitDepthY == BitDepthC, in which case - we could just omit two shifts. The second most common case is probably - BitDepthY>BitDepthC, for which we could also eliminate one shift. The remaining - case is also one shift only. - */ - - residualy*nT+x += (tctx->ResScaleVal * - static_cast<int32_t>((static_cast<uint32_t>(tctx->residual_lumay*nT+x) << BitDepthC ) >> BitDepthY ) ) >> 3; - } + const int shift = BitDepthY - BitDepthC; + + if (shift >= 0) { + for (int y=0;y<nT;y++) + for (int x=0;x<nT;x++) { + residualy*nT+x += (ResScaleVal * (tctx->residual_lumay*nT+x >> shift)) >> 3; + } + } + else { + const int32_t factor = 1 << (-shift); + + for (int y=0;y<nT;y++) + for (int x=0;x<nT;x++) { + residualy*nT+x += (ResScaleVal * (tctx->residual_lumay*nT+x * factor)) >> 3; + } + } }
View file
libde265-1.1.2.tar.gz/libde265/util.h -> libde265-1.1.3.tar.gz/libde265/util.h
Changed
@@ -49,14 +49,6 @@ #define unlikely(x) __builtin_expect(!!(x), 0) #endif -#if defined(__GNUC__) && (__GNUC__ >= 4) -#define LIBDE265_CHECK_RESULT __attribute__ ((warn_unused_result)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1700) -#define LIBDE265_CHECK_RESULT _Check_return_ -#else -#define LIBDE265_CHECK_RESULT -#endif - // Be careful with these alignment instructions. They only specify the alignment within // a struct. But they cannot make sure that the base address of the struct has the same alignment // when it is dynamically allocated. @@ -65,6 +57,16 @@ #define ALIGNED_8( var ) LIBDE265_DECLARE_ALIGNED( var, 8 ) #define ALIGNED_4( var ) LIBDE265_DECLARE_ALIGNED( var, 4 ) +// Force inlining of a function. Used where the compiler's heuristics would +// otherwise leave a large helper as a separate call on a hot path. +#if defined(_MSC_VER) +#define LIBDE265_ALWAYS_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +#define LIBDE265_ALWAYS_INLINE inline __attribute__((always_inline)) +#else +#define LIBDE265_ALWAYS_INLINE inline +#endif + #ifdef _MSC_VER #ifdef _CPPRTTI #define RTTI_ENABLED
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.