16fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/* 26fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * 46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Use of this source code is governed by a BSD-style license 56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * that can be found in the LICENSE file in the root of the source 66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * tree. An additional intellectual property rights grant can be found 76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * in the file PATENTS. All contributing project authors may 86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * be found in the AUTHORS file in the root of the source tree. 96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "vpx_ports/mem.h" 126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "vpx_mem/vpx_mem.h" 136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 140e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org#include "vp9/decoder/vp9_reader.h" 153358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org 1647265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org// This is meant to be a large, positive constant that can still be efficiently 1747265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org// loaded as an immediate (on platforms like ARM, for example). 1847265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org// Even relatively modest values like 100 would work fine. 1953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org#define LOTS_OF_BITS 0x40000000 2047265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org 21693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.comint vp9_reader_init(vp9_reader *r, 22693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com const uint8_t *buffer, 23693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com size_t size, 24693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com vpx_decrypt_cb decrypt_cb, 25693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com void *decrypt_state) { 26d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org if (size && !buffer) { 2710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org return 1; 28d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org } else { 29d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org r->buffer_end = buffer + size; 30d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org r->buffer = buffer; 31d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org r->value = 0; 32d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org r->count = -8; 33d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org r->range = 255; 34693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com r->decrypt_cb = decrypt_cb; 35693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com r->decrypt_state = decrypt_state; 36d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org vp9_reader_fill(r); 37d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org return vp9_read_bit(r) != 0; // marker bit 38d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org } 396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4110a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.orgvoid vp9_reader_fill(vp9_reader *r) { 4210a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org const uint8_t *const buffer_end = r->buffer_end; 4310a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org const uint8_t *buffer = r->buffer; 44693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com const uint8_t *buffer_start = buffer; 45d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org BD_VALUE value = r->value; 4610a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org int count = r->count; 47d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org int shift = BD_VALUE_SIZE - CHAR_BIT - (count + CHAR_BIT); 483358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org int loop_end = 0; 49693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com const size_t bytes_left = buffer_end - buffer; 50693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com const size_t bits_left = bytes_left * CHAR_BIT; 51693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com const int x = (int)(shift + CHAR_BIT - bits_left); 52693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com 53693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com if (r->decrypt_cb) { 54693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com size_t n = MIN(sizeof(r->clear_buffer), bytes_left); 55693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com r->decrypt_cb(r->decrypt_state, buffer, r->clear_buffer, (int)n); 56693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com buffer = r->clear_buffer; 57693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com buffer_start = r->clear_buffer; 58693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com } 593358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org 603358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org if (x >= 0) { 6153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org count += LOTS_OF_BITS; 623358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org loop_end = x; 633358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org } 646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 653358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org if (x < 0 || bits_left) { 663358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org while (shift >= loop_end) { 673358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org count += CHAR_BIT; 68d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org value |= (BD_VALUE)*buffer++ << shift; 693358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org shift -= CHAR_BIT; 703358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org } 713358b313481c08268259f41f6c0ebeb5272c18cfjohannkoenig@chromium.org } 726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 73693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com // NOTE: Variable 'buffer' may not relate to 'r->buffer' after decryption, 74693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com // so we increase 'r->buffer' by the amount that 'buffer' moved, rather than 75693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com // assign 'buffer' to 'r->buffer'. 76693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com r->buffer += buffer - buffer_start; 7710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org r->value = value; 7810a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org r->count = count; 796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8110a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.orgconst uint8_t *vp9_reader_find_end(vp9_reader *r) { 8210a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org // Find the end of the coded buffer 8353a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org while (r->count > CHAR_BIT && r->count < BD_VALUE_SIZE) { 8410a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org r->count -= CHAR_BIT; 8510a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org r->buffer--; 866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 8710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org return r->buffer; 886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 9047265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.orgint vp9_reader_has_error(vp9_reader *r) { 9147265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // Check if we have reached the end of the buffer. 9247265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 9347265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // Variable 'count' stores the number of bits in the 'value' buffer, minus 9447265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 8. The top byte is part of the algorithm, and the remainder is buffered 9547265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // to be shifted into it. So if count == 8, the top 16 bits of 'value' are 9647265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // occupied, 8 for the algorithm and 8 in the buffer. 9747265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 9847265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // When reading a byte from the user's buffer, count is filled with 8 and 9947265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // one byte is filled into the value buffer. When we reach the end of the 10053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // data, count is additionally filled with LOTS_OF_BITS. So when 10153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // count == LOTS_OF_BITS - 1, the user's data has been exhausted. 10247265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 10347265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 1 if we have tried to decode bits after the end of stream was encountered. 10447265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org // 0 No error. 10553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org return r->count > BD_VALUE_SIZE && r->count < LOTS_OF_BITS; 10647265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org} 107