/* * DVD-Audio Decoder plugin * Copyright (c) 2009-2024 Maxim V.Anisiutkin * * DVD-Audio Decoder is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * DVD-Audio Decoder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once template class stream_buffer_t { T* bank[2]; int bank_id; I bank_base; I bank_size; I min_read_size; I avg_write_size; T* read_ptr[2]; T* read_end[2]; bool banks_switched; public: stream_buffer_t(void) { bank[0] = bank[1] = (T*)0; bank_size = 0; } ~stream_buffer_t(void) { free(); } bool init(I _bank_size, I _min_read_size, I _avg_write_size) { free(); bank[0] = (T*)malloc((size_t)(_bank_size + _min_read_size) * sizeof(T)); bank[1] = (T*)malloc((size_t)(_bank_size + _min_read_size) * sizeof(T)); if (bank[0] == (T*)0 || bank[1] == (T*)0) { free(); return false; } bank_id = 0; bank_base = _min_read_size; bank_size = _bank_size; min_read_size = _min_read_size; avg_write_size = _avg_write_size; read_ptr[0] = read_end[0] = bank[0] + bank_base; read_ptr[1] = read_end[1] = bank[1] + bank_base; banks_switched = false; return true; } void reinit() { bank_id = 0; read_ptr[0] = read_end[0] = bank[0] + bank_base; read_ptr[1] = read_end[1] = bank[1] + bank_base; } void free(void) { if (bank[0] != (T*)0) { ::free(bank[0]); bank[0] = (T*)0; } if (bank[1] != (T*)0) { ::free(bank[1]); bank[1] = (T*)0; } bank_size = 0; } int get_next_bank(int p_bank_id) { return ~p_bank_id & 1; } I get_bank_size(void) { return bank_size; } T* get_read_ptr(void) { return read_ptr[bank_id]; } T* move_read_ptr(I size) { T* new_ptr = (T*)0; if (read_ptr[bank_id] + min_read_size + size <= read_end[bank_id]) read_ptr[bank_id] += size; else { int next_bank_id = get_next_bank(bank_id); T* read_ptr_rest = read_ptr[bank_id] + size; I read_size_rest = read_end[bank_id] - read_ptr_rest; if (read_ptr[bank_id] + size < read_end[bank_id]) memcpy(bank[next_bank_id] + bank_base - read_size_rest, read_ptr[bank_id] + size, read_size_rest); read_ptr[next_bank_id] = bank[next_bank_id] + bank_base - read_size_rest; read_ptr[bank_id] = read_end[bank_id] = bank[bank_id] + bank_base; switch_banks(); } new_ptr = read_ptr[bank_id]; return new_ptr; } I get_read_size(void) { I read_size; read_size = read_end[bank_id] - read_ptr[bank_id]; return read_size; } I set_read_size(I size) { I read_size = 0; if (read_ptr[bank_id] + size <= bank[bank_id] + bank_base + bank_size) { read_end[bank] = read_ptr[bank_id] + read_size; read_size = size; } return read_size; } T* get_write_ptr(void) { int bank_wr = get_next_bank(bank_id); return read_end[bank_wr]; } T* move_write_ptr(I size) { T* new_ptr = (T*)0; int bank_wr = get_next_bank(bank_id); if (read_end[bank_wr] + size <= bank[bank_wr] + bank_base + bank_size) { read_end[bank_wr] += size; new_ptr = read_end[bank_wr]; } return new_ptr; } I get_write_size(void) { I write_size; int bank_wr = get_next_bank(bank_id); write_size = bank[bank_wr] + bank_base + bank_size - read_end[bank_wr]; write_size = write_size < avg_write_size ? write_size : avg_write_size; return write_size; } bool is_ready_to_write() { return avg_write_size <= get_write_size(); } bool needs_data() { if (banks_switched) { banks_switched = false; return true; } return false; } private: void switch_banks() { bank_id = ~bank_id & 1; banks_switched = true; } };