box_content_decoder.cc (3203B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include "lib/jxl/box_content_decoder.h" 7 8 #include <algorithm> 9 #include <cstddef> 10 #include <cstdint> 11 #include <cstring> 12 13 #include "lib/jxl/base/sanitizers.h" 14 15 namespace jxl { 16 17 JxlBoxContentDecoder::JxlBoxContentDecoder() = default; 18 19 JxlBoxContentDecoder::~JxlBoxContentDecoder() { 20 if (brotli_dec) { 21 BrotliDecoderDestroyInstance(brotli_dec); 22 } 23 } 24 25 void JxlBoxContentDecoder::StartBox(bool brob_decode, bool box_until_eof, 26 size_t contents_size) { 27 if (brotli_dec) { 28 BrotliDecoderDestroyInstance(brotli_dec); 29 brotli_dec = nullptr; 30 } 31 header_done_ = false; 32 brob_decode_ = brob_decode; 33 box_until_eof_ = box_until_eof; 34 remaining_ = box_until_eof ? 0 : contents_size; 35 pos_ = 0; 36 } 37 38 JxlDecoderStatus JxlBoxContentDecoder::Process(const uint8_t* next_in, 39 size_t avail_in, size_t box_pos, 40 uint8_t** next_out, 41 size_t* avail_out) { 42 next_in += pos_ - box_pos; 43 avail_in -= pos_ - box_pos; 44 45 if (brob_decode_) { 46 if (!header_done_) { 47 if (avail_in < 4) return JXL_DEC_NEED_MORE_INPUT; 48 if (!box_until_eof_) { 49 if (remaining_ < 4) return JXL_DEC_ERROR; 50 remaining_ -= 4; 51 } 52 next_in += 4; 53 avail_in -= 4; 54 pos_ += 4; 55 header_done_ = true; 56 } 57 58 if (!brotli_dec) { 59 brotli_dec = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); 60 } 61 62 const uint8_t* next_in_before = next_in; 63 uint8_t* next_out_before = *next_out; 64 msan::MemoryIsInitialized(next_in, avail_in); 65 BrotliDecoderResult res = BrotliDecoderDecompressStream( 66 brotli_dec, &avail_in, &next_in, avail_out, next_out, nullptr); 67 size_t consumed = next_in - next_in_before; 68 size_t produced = *next_out - next_out_before; 69 if (res == BROTLI_DECODER_RESULT_ERROR) { 70 return JXL_DEC_ERROR; 71 } 72 msan::UnpoisonMemory(next_out_before, produced); 73 pos_ += consumed; 74 if (!box_until_eof_) remaining_ -= consumed; 75 if (res == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { 76 return JXL_DEC_NEED_MORE_INPUT; 77 } 78 if (res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { 79 return JXL_DEC_BOX_NEED_MORE_OUTPUT; 80 } 81 if (res == BROTLI_DECODER_RESULT_SUCCESS) { 82 return JXL_DEC_BOX_COMPLETE; 83 } 84 // unknown Brotli result 85 return JXL_DEC_ERROR; 86 } else { 87 // remaining box bytes as seen from dec->file_pos 88 size_t can_read = avail_in; 89 if (!box_until_eof_) can_read = std::min<size_t>(can_read, remaining_); 90 size_t to_write = std::min<size_t>(can_read, *avail_out); 91 memcpy(*next_out, next_in, to_write); 92 93 *next_out += to_write; 94 *avail_out -= to_write; 95 if (!box_until_eof_) remaining_ -= to_write; 96 pos_ += to_write; 97 98 if (to_write < can_read) return JXL_DEC_BOX_NEED_MORE_OUTPUT; 99 100 if (!box_until_eof_ && remaining_ > 0) return JXL_DEC_NEED_MORE_INPUT; 101 102 return JXL_DEC_BOX_COMPLETE; 103 } 104 } 105 106 } // namespace jxl