decoder/Client: add virtual method Read()
This commit is contained in:
parent
b488204093
commit
114fcee2ae
|
@ -401,6 +401,37 @@ DecoderBridge::OpenUri(const char *uri)
|
|||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
DecoderBridge::Read(InputStream &is, void *buffer, size_t length)
|
||||
try {
|
||||
assert(buffer != nullptr);
|
||||
assert(dc.state == DecoderState::START ||
|
||||
dc.state == DecoderState::DECODE);
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
ScopeLock lock(is.mutex);
|
||||
|
||||
while (true) {
|
||||
if (CheckCancelRead())
|
||||
return 0;
|
||||
|
||||
if (is.IsAvailable())
|
||||
break;
|
||||
|
||||
is.cond.wait(is.mutex);
|
||||
}
|
||||
|
||||
size_t nbytes = is.Read(buffer, length);
|
||||
assert(nbytes > 0 || is.IsEOF());
|
||||
|
||||
return nbytes;
|
||||
} catch (const std::runtime_error &e) {
|
||||
error = std::current_exception();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
DecoderBridge::SubmitTimestamp(double t)
|
||||
{
|
||||
|
|
|
@ -140,6 +140,7 @@ public:
|
|||
uint64_t GetSeekFrame() override;
|
||||
void SeekError() override;
|
||||
InputStreamPtr OpenUri(const char *uri) override;
|
||||
size_t Read(InputStream &is, void *buffer, size_t length) override;
|
||||
void SubmitTimestamp(double t) override;
|
||||
DecoderCommand SubmitData(InputStream *is,
|
||||
const void *data, size_t length,
|
||||
|
|
|
@ -98,6 +98,17 @@ public:
|
|||
*/
|
||||
virtual InputStreamPtr OpenUri(const char *uri) = 0;
|
||||
|
||||
/**
|
||||
* Blocking read from the input stream.
|
||||
*
|
||||
* @param is the input stream to read from
|
||||
* @param buffer the destination buffer
|
||||
* @param length the maximum number of bytes to read
|
||||
* @return the number of bytes read, or 0 if one of the following
|
||||
* occurs: end of file; error; command (like SEEK or STOP).
|
||||
*/
|
||||
virtual size_t Read(InputStream &is, void *buffer, size_t length) = 0;
|
||||
|
||||
/**
|
||||
* Sets the time stamp for the next data chunk [seconds]. The MPD
|
||||
* core automatically counts it up, and a decoder plugin only needs to
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "DecoderAPI.hxx"
|
||||
#include "DecoderControl.hxx"
|
||||
#include "Bridge.hxx"
|
||||
#include "input/InputStream.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
|
@ -30,44 +28,19 @@ size_t
|
|||
decoder_read(DecoderClient *client,
|
||||
InputStream &is,
|
||||
void *buffer, size_t length)
|
||||
try {
|
||||
{
|
||||
assert(buffer != nullptr);
|
||||
|
||||
/* XXX don't allow client==nullptr */
|
||||
if (client == nullptr)
|
||||
if (client != nullptr)
|
||||
return client->Read(is, buffer, length);
|
||||
|
||||
try {
|
||||
return is.LockRead(buffer, length);
|
||||
|
||||
auto &bridge = *(DecoderBridge *)client;
|
||||
|
||||
assert(bridge.dc.state == DecoderState::START ||
|
||||
bridge.dc.state == DecoderState::DECODE);
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
ScopeLock lock(is.mutex);
|
||||
|
||||
while (true) {
|
||||
if (bridge.CheckCancelRead())
|
||||
return 0;
|
||||
|
||||
if (is.IsAvailable())
|
||||
break;
|
||||
|
||||
is.cond.wait(is.mutex);
|
||||
}
|
||||
|
||||
size_t nbytes = is.Read(buffer, length);
|
||||
assert(nbytes > 0 || is.IsEOF());
|
||||
|
||||
return nbytes;
|
||||
} catch (const std::runtime_error &e) {
|
||||
auto *bridge = (DecoderBridge *)client;
|
||||
if (bridge != nullptr)
|
||||
bridge->error = std::current_exception();
|
||||
else
|
||||
} catch (const std::runtime_error &e) {
|
||||
LogError(e);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -80,51 +80,15 @@ FakeDecoder::OpenUri(const char *uri)
|
|||
}
|
||||
|
||||
size_t
|
||||
decoder_read(gcc_unused DecoderClient *client,
|
||||
InputStream &is,
|
||||
void *buffer, size_t length)
|
||||
FakeDecoder::Read(InputStream &is, void *buffer, size_t length)
|
||||
{
|
||||
try {
|
||||
return is.LockRead(buffer, length);
|
||||
} catch (const std::runtime_error &) {
|
||||
} catch (const std::runtime_error &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
decoder_read_full(DecoderClient *client, InputStream &is,
|
||||
void *_buffer, size_t size)
|
||||
{
|
||||
uint8_t *buffer = (uint8_t *)_buffer;
|
||||
|
||||
while (size > 0) {
|
||||
size_t nbytes = decoder_read(client, is, buffer, size);
|
||||
if (nbytes == 0)
|
||||
return false;
|
||||
|
||||
buffer += nbytes;
|
||||
size -= nbytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
decoder_skip(DecoderClient *client, InputStream &is, size_t size)
|
||||
{
|
||||
while (size > 0) {
|
||||
char buffer[1024];
|
||||
size_t nbytes = decoder_read(client, is, buffer,
|
||||
std::min(sizeof(buffer), size));
|
||||
if (nbytes == 0)
|
||||
return false;
|
||||
|
||||
size -= nbytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FakeDecoder::SubmitTimestamp(gcc_unused double t)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,7 @@ struct FakeDecoder final : DecoderClient {
|
|||
uint64_t GetSeekFrame() override;
|
||||
void SeekError() override;
|
||||
InputStreamPtr OpenUri(const char *uri) override;
|
||||
size_t Read(InputStream &is, void *buffer, size_t length) override;
|
||||
void SubmitTimestamp(double t) override;
|
||||
DecoderCommand SubmitData(InputStream *is,
|
||||
const void *data, size_t length,
|
||||
|
|
Loading…
Reference in New Issue