Commit 0b4fa41a authored by Max Kellermann's avatar Max Kellermann

InputStream: "protect" attributes

parent e138e2c8
...@@ -121,12 +121,12 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence) ...@@ -121,12 +121,12 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
AvioStream *stream = (AvioStream *)opaque; AvioStream *stream = (AvioStream *)opaque;
if (whence == AVSEEK_SIZE) if (whence == AVSEEK_SIZE)
return stream->input.size; return stream->input.GetSize();
if (!stream->input.LockSeek(pos, whence, IgnoreError())) if (!stream->input.LockSeek(pos, whence, IgnoreError()))
return -1; return -1;
return stream->input.offset; return stream->input.GetOffset();
} }
bool bool
...@@ -135,7 +135,7 @@ AvioStream::Open() ...@@ -135,7 +135,7 @@ AvioStream::Open()
io = avio_alloc_context(buffer, sizeof(buffer), io = avio_alloc_context(buffer, sizeof(buffer),
false, this, false, this,
mpd_ffmpeg_stream_read, nullptr, mpd_ffmpeg_stream_read, nullptr,
input.seekable input.IsSeekable()
? mpd_ffmpeg_stream_seek : nullptr); ? mpd_ffmpeg_stream_seek : nullptr);
return io != nullptr; return io != nullptr;
} }
...@@ -481,7 +481,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) ...@@ -481,7 +481,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
: 0; : 0;
decoder_initialized(decoder, audio_format, decoder_initialized(decoder, audio_format,
input.seekable, total_time); input.IsSeekable(), total_time);
#if LIBAVUTIL_VERSION_MAJOR >= 53 #if LIBAVUTIL_VERSION_MAJOR >= 53
AVFrame *frame = av_frame_alloc(); AVFrame *frame = av_frame_alloc();
......
...@@ -137,7 +137,7 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header) ...@@ -137,7 +137,7 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
data->frame_size = data->audio_format.GetFrameSize(); data->frame_size = data->audio_format.GetFrameSize();
decoder_initialized(data->decoder, data->audio_format, decoder_initialized(data->decoder, data->audio_format,
data->input_stream.seekable, data->input_stream.IsSeekable(),
(float)data->total_frames / (float)data->total_frames /
(float)data->audio_format.sample_rate); (float)data->audio_format.sample_rate);
......
...@@ -145,13 +145,13 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, ...@@ -145,13 +145,13 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
if (data->initialized) { if (data->initialized) {
/* done */ /* done */
decoder_initialized(data->decoder, data->audio_format, decoder_initialized(data->decoder, data->audio_format,
data->input_stream.seekable, data->input_stream.IsSeekable(),
(float)data->total_frames / (float)data->total_frames /
(float)data->audio_format.sample_rate); (float)data->audio_format.sample_rate);
return true; return true;
} }
if (data->input_stream.seekable) if (data->input_stream.IsSeekable())
/* allow the workaround below only for nonseekable /* allow the workaround below only for nonseekable
streams*/ streams*/
return false; return false;
......
...@@ -75,7 +75,7 @@ FlacIOTell(FLAC__IOHandle handle) ...@@ -75,7 +75,7 @@ FlacIOTell(FLAC__IOHandle handle)
{ {
InputStream *is = (InputStream *)handle; InputStream *is = (InputStream *)handle;
return is->offset; return is->GetOffset();
} }
static int static int
......
...@@ -37,7 +37,7 @@ ToFlacIOHandle(InputStream &is) ...@@ -37,7 +37,7 @@ ToFlacIOHandle(InputStream &is)
static inline const FLAC__IOCallbacks & static inline const FLAC__IOCallbacks &
GetFlacIOCallbacks(const InputStream &is) GetFlacIOCallbacks(const InputStream &is)
{ {
return is.seekable return is.IsSeekable()
? flac_io_callbacks_seekable ? flac_io_callbacks_seekable
: flac_io_callbacks; : flac_io_callbacks;
} }
......
...@@ -47,7 +47,7 @@ FlacInput::Read(FLAC__byte buffer[], size_t *bytes) ...@@ -47,7 +47,7 @@ FlacInput::Read(FLAC__byte buffer[], size_t *bytes)
FLAC__StreamDecoderSeekStatus FLAC__StreamDecoderSeekStatus
FlacInput::Seek(FLAC__uint64 absolute_byte_offset) FlacInput::Seek(FLAC__uint64 absolute_byte_offset)
{ {
if (!input_stream.seekable) if (!input_stream.IsSeekable())
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
::Error error; ::Error error;
...@@ -62,20 +62,20 @@ FlacInput::Seek(FLAC__uint64 absolute_byte_offset) ...@@ -62,20 +62,20 @@ FlacInput::Seek(FLAC__uint64 absolute_byte_offset)
FLAC__StreamDecoderTellStatus FLAC__StreamDecoderTellStatus
FlacInput::Tell(FLAC__uint64 *absolute_byte_offset) FlacInput::Tell(FLAC__uint64 *absolute_byte_offset)
{ {
if (!input_stream.seekable) if (!input_stream.IsSeekable())
return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
*absolute_byte_offset = (FLAC__uint64)input_stream.offset; *absolute_byte_offset = (FLAC__uint64)input_stream.GetOffset();
return FLAC__STREAM_DECODER_TELL_STATUS_OK; return FLAC__STREAM_DECODER_TELL_STATUS_OK;
} }
FLAC__StreamDecoderLengthStatus FLAC__StreamDecoderLengthStatus
FlacInput::Length(FLAC__uint64 *stream_length) FlacInput::Length(FLAC__uint64 *stream_length)
{ {
if (input_stream.size < 0) if (!input_stream.KnownSize())
return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
*stream_length = (FLAC__uint64)input_stream.size; *stream_length = (FLAC__uint64)input_stream.GetSize();
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
} }
......
...@@ -57,7 +57,7 @@ bool ...@@ -57,7 +57,7 @@ bool
OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet,
InputStream &is) InputStream &is)
{ {
if (is.size > 0 && is.size - is.offset < 65536) if (is.KnownSize() && is.GetRest() < 65536)
return OggFindEOS(oy, os, packet); return OggFindEOS(oy, os, packet);
if (!is.CheapSeeking()) if (!is.CheapSeeking())
......
...@@ -185,7 +185,7 @@ LoadEOSPacket(InputStream &is, Decoder *decoder, int serialno, ...@@ -185,7 +185,7 @@ LoadEOSPacket(InputStream &is, Decoder *decoder, int serialno,
troubl */ troubl */
return -1; return -1;
const auto old_offset = is.offset; const auto old_offset = is.GetOffset();
if (old_offset < 0) if (old_offset < 0)
return -1; return -1;
...@@ -332,16 +332,16 @@ bool ...@@ -332,16 +332,16 @@ bool
MPDOpusDecoder::Seek(OggSyncState &oy, double where_s) MPDOpusDecoder::Seek(OggSyncState &oy, double where_s)
{ {
assert(eos_granulepos > 0); assert(eos_granulepos > 0);
assert(input_stream.seekable); assert(input_stream.IsSeekable());
assert(input_stream.size > 0); assert(input_stream.KnownSize());
assert(input_stream.offset >= 0); assert(input_stream.GetOffset() >= 0);
const ogg_int64_t where_granulepos(where_s * opus_sample_rate); const ogg_int64_t where_granulepos(where_s * opus_sample_rate);
/* interpolate the file offset where we expect to find the /* interpolate the file offset where we expect to find the
given granule position */ given granule position */
/* TODO: implement binary search */ /* TODO: implement binary search */
InputStream::offset_type offset(where_granulepos * input_stream.size InputStream::offset_type offset(where_granulepos * input_stream.GetSize()
/ eos_granulepos); / eos_granulepos);
if (!OggSeekPageAtOffset(oy, os, input_stream, offset, SEEK_SET)) if (!OggSeekPageAtOffset(oy, os, input_stream, offset, SEEK_SET))
......
...@@ -88,7 +88,7 @@ static long ogg_tell_cb(void *data) ...@@ -88,7 +88,7 @@ static long ogg_tell_cb(void *data)
{ {
struct vorbis_input_stream *vis = (struct vorbis_input_stream *)data; struct vorbis_input_stream *vis = (struct vorbis_input_stream *)data;
return (long)vis->input_stream->offset; return (long)vis->input_stream->GetOffset();
} }
static const ov_callbacks vorbis_is_callbacks = { static const ov_callbacks vorbis_is_callbacks = {
......
...@@ -377,7 +377,7 @@ wavpack_input_read_bytes(void *id, void *data, int32_t bcount) ...@@ -377,7 +377,7 @@ wavpack_input_read_bytes(void *id, void *data, int32_t bcount)
static uint32_t static uint32_t
wavpack_input_get_pos(void *id) wavpack_input_get_pos(void *id)
{ {
return wpin(id)->is->offset; return wpin(id)->is->GetOffset();
} }
static int static int
...@@ -406,16 +406,16 @@ wavpack_input_push_back_byte(void *id, int c) ...@@ -406,16 +406,16 @@ wavpack_input_push_back_byte(void *id, int c)
static uint32_t static uint32_t
wavpack_input_get_length(void *id) wavpack_input_get_length(void *id)
{ {
if (wpin(id)->is->size < 0) if (!wpin(id)->is->KnownSize())
return 0; return 0;
return wpin(id)->is->size; return wpin(id)->is->GetSize();
} }
static int static int
wavpack_input_can_seek(void *id) wavpack_input_can_seek(void *id)
{ {
return wpin(id)->is->seekable; return wpin(id)->is->IsSeekable();
} }
static WavpackStreamReader mpd_is_reader = { static WavpackStreamReader mpd_is_reader = {
...@@ -484,7 +484,7 @@ static void ...@@ -484,7 +484,7 @@ static void
wavpack_streamdecode(Decoder &decoder, InputStream &is) wavpack_streamdecode(Decoder &decoder, InputStream &is)
{ {
int open_flags = OPEN_NORMALIZE; int open_flags = OPEN_NORMALIZE;
bool can_seek = is.seekable; bool can_seek = is.IsSeekable();
wavpack_input isp_wvc; wavpack_input isp_wvc;
InputStream *is_wvc = wavpack_open_wvc(decoder, is.GetURI(), InputStream *is_wvc = wavpack_open_wvc(decoder, is.GetURI(),
...@@ -492,7 +492,7 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is) ...@@ -492,7 +492,7 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is)
&isp_wvc); &isp_wvc);
if (is_wvc != nullptr) { if (is_wvc != nullptr) {
open_flags |= OPEN_WVC; open_flags |= OPEN_WVC;
can_seek &= is_wvc->seekable; can_seek &= is_wvc->IsSeekable();
} }
if (!can_seek) { if (!can_seek) {
......
...@@ -64,6 +64,7 @@ public: ...@@ -64,6 +64,7 @@ public:
*/ */
Cond &cond; Cond &cond;
protected:
/** /**
* indicates whether the stream is ready for reading and * indicates whether the stream is ready for reading and
* whether the other attributes in this struct are valid * whether the other attributes in this struct are valid
...@@ -80,7 +81,6 @@ public: ...@@ -80,7 +81,6 @@ public:
*/ */
offset_type size; offset_type size;
public:
/** /**
* the current offset within the stream * the current offset within the stream
*/ */
...@@ -218,6 +218,13 @@ public: ...@@ -218,6 +218,13 @@ public:
} }
gcc_pure gcc_pure
bool KnownSize() const {
assert(ready);
return size >= 0;
}
gcc_pure
offset_type GetSize() const { offset_type GetSize() const {
assert(ready); assert(ready);
...@@ -240,6 +247,15 @@ public: ...@@ -240,6 +247,15 @@ public:
} }
gcc_pure gcc_pure
offset_type GetRest() const {
assert(ready);
assert(size >= 0);
assert(offset >= 0);
return size - offset;
}
gcc_pure
bool IsSeekable() const { bool IsSeekable() const {
assert(ready); assert(ready);
......
...@@ -93,7 +93,7 @@ private: ...@@ -93,7 +93,7 @@ private:
* buffer contain more data for the next read operation? * buffer contain more data for the next read operation?
*/ */
bool ReadingFromBuffer() const { bool ReadingFromBuffer() const {
return tail > 0 && offset < input->offset; return tail > 0 && offset < input->GetOffset();
} }
/** /**
...@@ -116,7 +116,7 @@ private: ...@@ -116,7 +116,7 @@ private:
SetReady(); SetReady();
} }
offset = src->offset; offset = src->GetOffset();
} }
}; };
...@@ -127,7 +127,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error) ...@@ -127,7 +127,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error)
/* buffered read */ /* buffered read */
assert(head == (size_t)offset); assert(head == (size_t)offset);
assert(tail == (size_t)input->offset); assert(tail == (size_t)input->GetOffset());
if (read_size > tail - head) if (read_size > tail - head)
read_size = tail - head; read_size = tail - head;
...@@ -142,7 +142,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error) ...@@ -142,7 +142,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error)
size_t nbytes = input->Read(ptr, read_size, error); size_t nbytes = input->Read(ptr, read_size, error);
if (input->offset > (InputPlugin::offset_type)sizeof(buffer)) if (input->GetOffset() > (offset_type)sizeof(buffer))
/* disable buffering */ /* disable buffering */
tail = 0; tail = 0;
else if (tail == (size_t)offset) { else if (tail == (size_t)offset) {
...@@ -151,7 +151,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error) ...@@ -151,7 +151,7 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error)
memcpy(buffer + tail, ptr, nbytes); memcpy(buffer + tail, ptr, nbytes);
tail += nbytes; tail += nbytes;
assert(tail == (size_t)input->offset); assert(tail == (size_t)input->GetOffset());
} }
CopyAttributes(); CopyAttributes();
...@@ -172,7 +172,7 @@ RewindInputStream::Seek(InputPlugin::offset_type new_offset, int whence, ...@@ -172,7 +172,7 @@ RewindInputStream::Seek(InputPlugin::offset_type new_offset, int whence,
assert(!ReadingFromBuffer() || assert(!ReadingFromBuffer() ||
head == (size_t)offset); head == (size_t)offset);
assert(tail == (size_t)input->offset); assert(tail == (size_t)input->GetOffset());
head = (size_t)new_offset; head = (size_t)new_offset;
offset = new_offset; offset = new_offset;
...@@ -194,7 +194,7 @@ InputStream * ...@@ -194,7 +194,7 @@ InputStream *
input_rewind_open(InputStream *is) input_rewind_open(InputStream *is)
{ {
assert(is != nullptr); assert(is != nullptr);
assert(is->offset == 0); assert(is->GetOffset() == 0);
if (is->IsReady() && is->IsSeekable()) if (is->IsReady() && is->IsSeekable())
/* seekable resources don't need this plugin */ /* seekable resources don't need this plugin */
......
...@@ -51,7 +51,7 @@ ExpatParser::Parse(const char *data, size_t length, bool is_final, ...@@ -51,7 +51,7 @@ ExpatParser::Parse(const char *data, size_t length, bool is_final,
bool bool
ExpatParser::Parse(InputStream &is, Error &error) ExpatParser::Parse(InputStream &is, Error &error)
{ {
assert(is.ready); assert(is.IsReady());
while (true) { while (true) {
char buffer[4096]; char buffer[4096];
......
...@@ -248,7 +248,7 @@ playlist_list_open_stream_suffix(InputStream &is, const char *suffix) ...@@ -248,7 +248,7 @@ playlist_list_open_stream_suffix(InputStream &is, const char *suffix)
SongEnumerator * SongEnumerator *
playlist_list_open_stream(InputStream &is, const char *uri) playlist_list_open_stream(InputStream &is, const char *uri)
{ {
assert(is.ready); assert(is.IsReady());
const char *const mime = is.GetMimeType(); const char *const mime = is.GetMimeType();
if (mime != nullptr) { if (mime != nullptr) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment