You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.2 KiB
C++
149 lines
4.2 KiB
C++
/*
|
|
* DVD-Audio Decoder plugin
|
|
* Copyright (c) 2009-2024 Maxim V.Anisiutkin <maxim.anisiutkin@gmail.com>
|
|
*
|
|
* 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 T, class I> 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;
|
|
}
|
|
};
|