Commit ec3df94f authored by Stefan Westerfeld's avatar Stefan Westerfeld

Avoid HLS temp file for accessing lossless context.

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 0c44a4c6
......@@ -29,12 +29,21 @@ SFInputStream::~SFInputStream()
Error
SFInputStream::open (const string& filename)
{
return open ([&] (SF_INFO *sfinfo) {
return sf_open (filename.c_str(), SFM_READ, sfinfo);
});
}
Error
SFInputStream::open (std::function<SNDFILE* (SF_INFO *)> open_func)
{
assert (m_state == State::NEW);
SF_INFO sfinfo = { 0, };
m_sndfile = sf_open (filename.c_str(), SFM_READ, &sfinfo);
m_sndfile = open_func (&sfinfo);
int error = sf_error (m_sndfile);
if (error)
......@@ -155,3 +164,96 @@ SFInputStream::close()
m_state = State::CLOSED;
}
}
static sf_count_t
virtual_get_len (void *data)
{
SFInputStream::VirtualData *vdata = static_cast<SFInputStream::VirtualData *> (data);
return vdata->mem->size();
}
static sf_count_t
virtual_seek (sf_count_t offset, int whence, void *data)
{
SFInputStream::VirtualData *vdata = static_cast<SFInputStream::VirtualData *> (data);
if (whence == SEEK_CUR)
{
vdata->offset = vdata->offset + offset;
}
else if (whence == SEEK_SET)
{
vdata->offset = offset;
}
else if (whence == SEEK_END)
{
vdata->offset = vdata->mem->size() + offset;
}
/* can't seek beyond eof */
vdata->offset = bound<sf_count_t> (0, vdata->offset, vdata->mem->size());
return vdata->offset;
}
static sf_count_t
virtual_read (void *ptr, sf_count_t count, void *data)
{
SFInputStream::VirtualData *vdata = static_cast<SFInputStream::VirtualData *> (data);
int rcount = 0;
unsigned char *uptr = static_cast<unsigned char *> (ptr);
for (sf_count_t i = 0; i < count; i++)
{
size_t rpos = i + vdata->offset;
if (rpos < vdata->mem->size())
{
uptr[i] = (*vdata->mem)[rpos];
rcount++;
}
}
vdata->offset += rcount;
return rcount;
}
static sf_count_t
virtual_write (const void *ptr, sf_count_t count, void *data)
{
SFInputStream::VirtualData *vdata = static_cast<SFInputStream::VirtualData *> (data);
const unsigned char *uptr = static_cast<const unsigned char *> (ptr);
for (sf_count_t i = 0; i < count; i++)
{
unsigned char ch = uptr[i];
size_t wpos = i + vdata->offset;
if (wpos >= vdata->mem->size())
vdata->mem->resize (wpos + 1);
(*vdata->mem)[wpos] = ch;
}
vdata->offset += count;
return count;
}
static sf_count_t
virtual_tell (void *data)
{
SFInputStream::VirtualData *vdata = static_cast<SFInputStream::VirtualData *> (data);
return vdata->offset;
}
Error
SFInputStream::open (const vector<unsigned char> *data)
{
virtual_data.mem = const_cast<vector<unsigned char> *> (data);
SF_VIRTUAL_IO sf_virtual_io = {
virtual_get_len,
virtual_seek,
virtual_read,
virtual_write,
virtual_tell
};
return open ([&] (SF_INFO *sfinfo) {
return sf_open_virtual (&sf_virtual_io, SFM_READ, sfinfo, &virtual_data);
});
}
......@@ -19,6 +19,7 @@
#define AUDIOWMARK_SF_INPUT_STREAM_HH
#include <string>
#include <functional>
#include <sndfile.h>
......@@ -26,6 +27,16 @@
class SFInputStream : public AudioInputStream
{
public:
/* to support read from memory */
struct VirtualData
{
std::vector<unsigned char> *mem = nullptr;
sf_count_t offset = 0;
};
private:
VirtualData virtual_data;
SNDFILE *m_sndfile = nullptr;
int m_n_channels = 0;
int m_n_values = 0;
......@@ -40,10 +51,12 @@ class SFInputStream : public AudioInputStream
};
State m_state = State::NEW;
Error open (std::function<SNDFILE* (SF_INFO *)> open_func);
public:
~SFInputStream();
Error open (const std::string& filename);
Error open (const std::vector<unsigned char> *data);
Error read_frames (std::vector<float>& samples, size_t count) override;
void close();
......
......@@ -24,6 +24,7 @@
#include "mpegts.hh"
#include "wavdata.hh"
#include "wmcommon.hh"
#include "sfinputstream.hh"
using std::string;
using std::regex;
......@@ -76,21 +77,16 @@ ff_decode (const string& filename, WavData& out_wav_data)
Error
decode_context (const TSReader& reader, WavData& out_wav_data)
{
FILE *tmp_file = tmpfile();
ScopedFile tmp_file_s (tmp_file);
string tmp_file_name = string_printf ("/dev/fd/%d", fileno (tmp_file));
/* write wav data */
auto full_wav = reader.find ("full.wav");
if (!full_wav)
return Error ("no embedded context found");
size_t r = fwrite (full_wav->data.data(), 1, full_wav->data.size(), tmp_file);
if (r != full_wav->data.size())
return Error (string_printf ("unable to write decode_context"));
fflush (tmp_file);
SFInputStream input_stream;
Error err = input_stream.open (&full_wav->data);
if (err)
return err;
Error err = out_wav_data.load (tmp_file_name);
err = out_wav_data.load (&input_stream);
return err;
}
......
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