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
|
void
|
||||||
DecoderBridge::SubmitTimestamp(double t)
|
DecoderBridge::SubmitTimestamp(double t)
|
||||||
{
|
{
|
||||||
|
@ -140,6 +140,7 @@ public:
|
|||||||
uint64_t GetSeekFrame() override;
|
uint64_t GetSeekFrame() override;
|
||||||
void SeekError() override;
|
void SeekError() override;
|
||||||
InputStreamPtr OpenUri(const char *uri) override;
|
InputStreamPtr OpenUri(const char *uri) override;
|
||||||
|
size_t Read(InputStream &is, void *buffer, size_t length) override;
|
||||||
void SubmitTimestamp(double t) override;
|
void SubmitTimestamp(double t) override;
|
||||||
DecoderCommand SubmitData(InputStream *is,
|
DecoderCommand SubmitData(InputStream *is,
|
||||||
const void *data, size_t length,
|
const void *data, size_t length,
|
||||||
|
@ -98,6 +98,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual InputStreamPtr OpenUri(const char *uri) = 0;
|
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
|
* Sets the time stamp for the next data chunk [seconds]. The MPD
|
||||||
* core automatically counts it up, and a decoder plugin only needs to
|
* core automatically counts it up, and a decoder plugin only needs to
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "DecoderAPI.hxx"
|
#include "DecoderAPI.hxx"
|
||||||
#include "DecoderControl.hxx"
|
|
||||||
#include "Bridge.hxx"
|
|
||||||
#include "input/InputStream.hxx"
|
#include "input/InputStream.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -30,44 +28,19 @@ size_t
|
|||||||
decoder_read(DecoderClient *client,
|
decoder_read(DecoderClient *client,
|
||||||
InputStream &is,
|
InputStream &is,
|
||||||
void *buffer, size_t length)
|
void *buffer, size_t length)
|
||||||
try {
|
{
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
|
|
||||||
/* XXX don't allow client==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);
|
return is.LockRead(buffer, length);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
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
|
|
||||||
LogError(e);
|
LogError(e);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -80,51 +80,15 @@ FakeDecoder::OpenUri(const char *uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
decoder_read(gcc_unused DecoderClient *client,
|
FakeDecoder::Read(InputStream &is, void *buffer, size_t length)
|
||||||
InputStream &is,
|
|
||||||
void *buffer, size_t length)
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return is.LockRead(buffer, length);
|
return is.LockRead(buffer, length);
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &e) {
|
||||||
return 0;
|
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
|
void
|
||||||
FakeDecoder::SubmitTimestamp(gcc_unused double t)
|
FakeDecoder::SubmitTimestamp(gcc_unused double t)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,7 @@ struct FakeDecoder final : DecoderClient {
|
|||||||
uint64_t GetSeekFrame() override;
|
uint64_t GetSeekFrame() override;
|
||||||
void SeekError() override;
|
void SeekError() override;
|
||||||
InputStreamPtr OpenUri(const char *uri) override;
|
InputStreamPtr OpenUri(const char *uri) override;
|
||||||
|
size_t Read(InputStream &is, void *buffer, size_t length) override;
|
||||||
void SubmitTimestamp(double t) override;
|
void SubmitTimestamp(double t) override;
|
||||||
DecoderCommand SubmitData(InputStream *is,
|
DecoderCommand SubmitData(InputStream *is,
|
||||||
const void *data, size_t length,
|
const void *data, size_t length,
|
||||||
|
Loading…
Reference in New Issue
Block a user