Mercurial > hg > piper-cpp
changeset 44:a98ef4c2616b
Make base64/text selectable when serialising process and feature blocks; add base64 version as an output format for vampipe-convert; make VamPipePluginLibrary switch to returning base64 encoding as soon as it is fed any as input
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 08 Sep 2016 15:27:48 +0100 |
parents | 62c17e143aba |
children | 7668fbdcfb15 |
files | json/VampJson.h utilities/json-to-capnp.cpp utilities/vampipe-convert.cpp |
diffstat | 3 files changed, 97 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/json/VampJson.h Wed Aug 24 10:50:40 2016 +0100 +++ b/json/VampJson.h Thu Sep 08 15:27:48 2016 +0100 @@ -59,6 +59,12 @@ class VampJson { public: + /// Serialisation format for arrays of floats (process input and feature values) + enum class BufferSerialisation { + Text, // default JSON serialisation of values in array form + Base64 // base64-encoded string of the raw data as packed ieee 32-bit floats + }; + class Failure : virtual public std::runtime_error { public: Failure(std::string s) : runtime_error(s) { } @@ -308,11 +314,12 @@ } static json11::Json - fromFeature(const Vamp::Plugin::Feature &f, bool asText) { + fromFeature(const Vamp::Plugin::Feature &f, + BufferSerialisation serialisation) { json11::Json::object jo; if (f.values.size() > 0) { - if (asText) { + if (serialisation == BufferSerialisation::Text) { jo["values"] = json11::Json::array(f.values.begin(), f.values.end()); } else { @@ -333,7 +340,8 @@ } static Vamp::Plugin::Feature - toFeature(json11::Json j) { + toFeature(json11::Json j, + BufferSerialisation &serialisation) { Vamp::Plugin::Feature f; if (!j.is_object()) { @@ -349,23 +357,26 @@ } if (j["b64values"].is_string()) { f.values = toFloatBuffer(j["b64values"].string_value()); + serialisation = BufferSerialisation::Base64; } else if (j["values"].is_array()) { for (auto v : j["values"].array_items()) { f.values.push_back(v.number_value()); } + serialisation = BufferSerialisation::Text; } f.label = j["label"].string_value(); return f; } static json11::Json - fromFeatureSet(const Vamp::Plugin::FeatureSet &fs, bool asText) { + fromFeatureSet(const Vamp::Plugin::FeatureSet &fs, + BufferSerialisation serialisation) { json11::Json::object jo; for (const auto &fsi : fs) { std::vector<json11::Json> fj; for (const Vamp::Plugin::Feature &f: fsi.second) { - fj.push_back(fromFeature(f, asText)); + fj.push_back(fromFeature(f, serialisation)); } std::stringstream sstr; sstr << fsi.first; @@ -376,20 +387,21 @@ } static Vamp::Plugin::FeatureList - toFeatureList(json11::Json j) { + toFeatureList(json11::Json j, + BufferSerialisation &serialisation) { Vamp::Plugin::FeatureList fl; if (!j.is_array()) { throw Failure("array expected for feature list"); } for (const json11::Json &fj : j.array_items()) { - fl.push_back(toFeature(fj)); + fl.push_back(toFeature(fj, serialisation)); } return fl; } static Vamp::Plugin::FeatureSet - toFeatureSet(json11::Json j) { + toFeatureSet(json11::Json j, BufferSerialisation &serialisation) { Vamp::Plugin::FeatureSet fs; if (!j.is_object()) { @@ -402,7 +414,7 @@ if (n < 0 || fs.find(n) != fs.end() || count < nstr.size()) { throw Failure("invalid or duplicate numerical index for output"); } - fs[n] = toFeatureList(entry.second); + fs[n] = toFeatureList(entry.second, serialisation); } return fs; } @@ -802,7 +814,8 @@ static json11::Json fromProcessRequest(const Vamp::HostExt::ProcessRequest &r, - const PluginHandleMapper &mapper) { + const PluginHandleMapper &mapper, + BufferSerialisation serialisation) { json11::Json::object jo; jo["pluginHandle"] = mapper.pluginToHandle(r.plugin); @@ -813,8 +826,13 @@ json11::Json::array chans; for (size_t i = 0; i < r.inputBuffers.size(); ++i) { json11::Json::object c; - c["b64values"] = fromFloatBuffer(r.inputBuffers[i].data(), - r.inputBuffers[i].size()); + if (serialisation == BufferSerialisation::Text) { + c["values"] = json11::Json::array(r.inputBuffers[i].begin(), + r.inputBuffers[i].end()); + } else { + c["b64values"] = fromFloatBuffer(r.inputBuffers[i].data(), + r.inputBuffers[i].size()); + } chans.push_back(c); } io["inputBuffers"] = chans; @@ -824,7 +842,9 @@ } static Vamp::HostExt::ProcessRequest - toProcessRequest(json11::Json j, const PluginHandleMapper &mapper) { + toProcessRequest(json11::Json j, + const PluginHandleMapper &mapper, + BufferSerialisation &serialisation) { std::string err; @@ -848,15 +868,20 @@ r.timestamp = toRealTime(input["timestamp"]); for (auto a: input["inputBuffers"].array_items()) { + if (a["b64values"].is_string()) { - r.inputBuffers.push_back(toFloatBuffer - (a["b64values"].string_value())); + std::vector<float> buf = toFloatBuffer(a["b64values"].string_value()); + r.inputBuffers.push_back(buf); + serialisation = BufferSerialisation::Base64; + } else if (a["values"].is_array()) { std::vector<float> buf; for (auto v : a["values"].array_items()) { buf.push_back(v.number_value()); } r.inputBuffers.push_back(buf); + serialisation = BufferSerialisation::Text; + } else { throw Failure("expected values or b64values in inputBuffers object"); } @@ -937,22 +962,24 @@ static json11::Json fromVampRequest_Process(const Vamp::HostExt::ProcessRequest &req, - const PluginHandleMapper &mapper) { + const PluginHandleMapper &mapper, + BufferSerialisation serialisation) { json11::Json::object jo; jo["type"] = "process"; - jo["content"] = fromProcessRequest(req, mapper); + jo["content"] = fromProcessRequest(req, mapper, serialisation); return json11::Json(jo); } static json11::Json - fromVampResponse_Process(const Vamp::HostExt::ProcessResponse &resp) { + fromVampResponse_Process(const Vamp::HostExt::ProcessResponse &resp, + BufferSerialisation serialisation) { json11::Json::object jo; jo["type"] = "process"; jo["success"] = true; jo["errorText"] = ""; - jo["content"] = fromFeatureSet(resp.features, true); + jo["content"] = fromFeatureSet(resp.features, serialisation); return json11::Json(jo); } @@ -969,13 +996,14 @@ } static json11::Json - fromVampResponse_Finish(const Vamp::HostExt::ProcessResponse &resp) { + fromVampResponse_Finish(const Vamp::HostExt::ProcessResponse &resp, + BufferSerialisation serialisation) { json11::Json::object jo; jo["type"] = "finish"; jo["success"] = true; jo["errorText"] = ""; - jo["content"] = fromFeatureSet(resp.features, true); + jo["content"] = fromFeatureSet(resp.features, serialisation); return json11::Json(jo); } @@ -1039,7 +1067,7 @@ type + "\""); } } - + static void toVampRequest_List(json11::Json j) { @@ -1093,18 +1121,19 @@ } static Vamp::HostExt::ProcessRequest - toVampRequest_Process(json11::Json j, const PluginHandleMapper &mapper) { + toVampRequest_Process(json11::Json j, const PluginHandleMapper &mapper, + BufferSerialisation &serialisation) { checkTypeField(j, "process"); - return toProcessRequest(j["content"], mapper); + return toProcessRequest(j["content"], mapper, serialisation); } static Vamp::HostExt::ProcessResponse - toVampResponse_Process(json11::Json j) { + toVampResponse_Process(json11::Json j, BufferSerialisation &serialisation) { Vamp::HostExt::ProcessResponse resp; if (successful(j)) { - resp.features = toFeatureSet(j["content"]); + resp.features = toFeatureSet(j["content"], serialisation); } return resp; } @@ -1117,11 +1146,11 @@ } static Vamp::HostExt::ProcessResponse - toVampResponse_Finish(json11::Json j) { + toVampResponse_Finish(json11::Json j, BufferSerialisation &serialisation) { Vamp::HostExt::ProcessResponse resp; if (successful(j)) { - resp.features = toFeatureSet(j["content"]); + resp.features = toFeatureSet(j["content"], serialisation); } return resp; }
--- a/utilities/json-to-capnp.cpp Wed Aug 24 10:50:40 2016 +0100 +++ b/utilities/json-to-capnp.cpp Thu Sep 08 15:27:48 2016 +0100 @@ -45,6 +45,7 @@ Json j = json_input(input); string type = j["type"].string_value(); Json payload = j["payload"]; + VampJson::BufferSerialisation serialisation; if (type == "configurationrequest") { auto req = message.initRoot<ConfigurationRequest>(); @@ -60,12 +61,12 @@ } else if (type == "feature") { auto f = message.initRoot<Feature>(); VampnProto::buildFeature - (f, VampJson::toFeature(payload)); + (f, VampJson::toFeature(payload, serialisation)); } else if (type == "featureset") { auto fs = message.initRoot<FeatureSet>(); VampnProto::buildFeatureSet - (fs, VampJson::toFeatureSet(payload)); + (fs, VampJson::toFeatureSet(payload, serialisation)); } else if (type == "loadrequest") { auto req = message.initRoot<LoadRequest>(); @@ -102,7 +103,7 @@ auto p = message.initRoot<ProcessRequest>(); PreservingPluginHandleMapper mapper; VampnProto::buildProcessRequest - (p, VampJson::toProcessRequest(payload, mapper), mapper); + (p, VampJson::toProcessRequest(payload, mapper, serialisation), mapper); } else if (type == "realtime") { auto b = message.initRoot<RealTime>();
--- a/utilities/vampipe-convert.cpp Wed Aug 24 10:50:40 2016 +0100 +++ b/utilities/vampipe-convert.cpp Thu Sep 08 15:27:48 2016 +0100 @@ -24,11 +24,14 @@ " <informat>: the format to read from stdin\n" " (\"json\" or \"capnp\", default is \"json\")\n" " <outformat>: the format to convert to and write to stdout\n" - " (\"json\" or \"capnp\", default is \"json\")\n" - " request|response: whether to expect Vamp request or response messages\n\n" + " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n" + " request|response: whether messages are Vamp request or response type\n\n" "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n" "If <informat> and <outformat> are the same, just check validity of incoming\n" - "messages and pass them to output.\n\n"; + "messages and pass them to output.\n\n" + "Specifying \"json-b64\" as output format forces base64 encoding for process and\n" + "feature blocks, unlike the \"json\" output format which uses text encoding.\n" + "The \"json\" input format accepts either.\n\n"; exit(2); } @@ -93,6 +96,7 @@ Json j = convertRequestJson(input); rr.type = VampJson::getRequestResponseType(j); + VampJson::BufferSerialisation serialisation = VampJson::BufferSerialisation::Text; switch (rr.type) { @@ -106,7 +110,7 @@ rr.configurationRequest = VampJson::toVampRequest_Configure(j, mapper); break; case RRType::Process: - rr.processRequest = VampJson::toVampRequest_Process(j, mapper); + rr.processRequest = VampJson::toVampRequest_Process(j, mapper, serialisation); break; case RRType::Finish: rr.finishPlugin = VampJson::toVampRequest_Finish(j, mapper); @@ -119,7 +123,7 @@ } void -writeRequestJson(RequestOrResponse &rr) +writeRequestJson(RequestOrResponse &rr, bool useBase64) { Json j; @@ -135,7 +139,11 @@ j = VampJson::fromVampRequest_Configure(rr.configurationRequest, mapper); break; case RRType::Process: - j = VampJson::fromVampRequest_Process(rr.processRequest, mapper); + j = VampJson::fromVampRequest_Process + (rr.processRequest, mapper, + useBase64 ? + VampJson::BufferSerialisation::Base64 : + VampJson::BufferSerialisation::Text); break; case RRType::Finish: j = VampJson::fromVampRequest_Finish(rr.finishPlugin, mapper); @@ -162,6 +170,7 @@ Json j = convertResponseJson(input); rr.type = VampJson::getRequestResponseType(j); + VampJson::BufferSerialisation serialisation = VampJson::BufferSerialisation::Text; switch (rr.type) { @@ -175,10 +184,10 @@ rr.configurationResponse = VampJson::toVampResponse_Configure(j); break; case RRType::Process: - rr.processResponse = VampJson::toVampResponse_Process(j); + rr.processResponse = VampJson::toVampResponse_Process(j, serialisation); break; case RRType::Finish: - rr.finishResponse = VampJson::toVampResponse_Finish(j); + rr.finishResponse = VampJson::toVampResponse_Finish(j, serialisation); break; case RRType::NotValid: break; @@ -188,7 +197,7 @@ } void -writeResponseJson(RequestOrResponse &rr) +writeResponseJson(RequestOrResponse &rr, bool useBase64) { Json j; @@ -204,10 +213,18 @@ j = VampJson::fromVampResponse_Configure(rr.configurationResponse); break; case RRType::Process: - j = VampJson::fromVampResponse_Process(rr.processResponse); + j = VampJson::fromVampResponse_Process + (rr.processResponse, + useBase64 ? + VampJson::BufferSerialisation::Base64 : + VampJson::BufferSerialisation::Text); break; case RRType::Finish: - j = VampJson::fromVampResponse_Finish(rr.finishResponse); + j = VampJson::fromVampResponse_Finish + (rr.finishResponse, + useBase64 ? + VampJson::BufferSerialisation::Base64 : + VampJson::BufferSerialisation::Text); break; case RRType::NotValid: break; @@ -393,9 +410,15 @@ { if (format == "json") { if (rr.direction == RequestOrResponse::Request) { - writeRequestJson(rr); + writeRequestJson(rr, false); } else { - writeResponseJson(rr); + writeResponseJson(rr, false); + } + } else if (format == "json-b64") { + if (rr.direction == RequestOrResponse::Request) { + writeRequestJson(rr, true); + } else { + writeResponseJson(rr, true); } } else if (format == "capnp") { if (rr.direction == RequestOrResponse::Request) {