arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
MultiDecoder.h
1
2#pragma once
3
4#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
5#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
6#include "AudioTools/CoreAudio/AudioMetaData/MimeDetector.h"
7#include "AudioTools/CoreAudio/AudioHttp/AbstractURLStream.h"
8
9namespace audio_tools {
10
21class MultiDecoder : public AudioDecoder {
22 public:
24 MultiDecoder() = default;
27
29 bool begin() override {
30 mime_detector.begin();
31 is_first = true;
32 return true;
33 }
34
36 void end() override {
37 if (actual_decoder.decoder != nullptr && actual_decoder.is_open) {
38 actual_decoder.decoder->end();
39 }
40 actual_decoder.is_open = false;
41 actual_decoder.decoder = nullptr;
42 actual_decoder.mime = nullptr;
43 is_first = true;
44 }
45
47 void addDecoder(AudioDecoder& decoder, const char* mime) {
48 DecoderInfo info{mime, &decoder};
49 decoder.addNotifyAudioChange(*this);
50 decoders.push_back(info);
51 }
52
55 void addDecoder(AudioDecoder& decoder, const char* mime,
56 bool (*check)(uint8_t* data, size_t len)) {
57 addDecoder(decoder, mime);
58 mime_detector.setCheck(mime, check);
59 }
60
61 virtual void setOutput(Print& out_stream) override {
62 p_print = &out_stream;
63 for (int j = 0; j < decoders.size(); j++) {
64 decoders[j].decoder->setOutput(out_stream);
65 }
66 }
67
69 void setMimeSource(AbstractURLStream& url) { p_url_stream = &url; }
70
73 bool selectDecoder(const char* mime) {
74 bool result = false;
75 // do nothing if no change
76 if (StrView(mime).equals(actual_decoder.mime)) {
77 is_first = false;
78 return true;
79 }
80 // close actual decoder
81 end();
82
83 // find the corresponding decoder
84 for (int j = 0; j < decoders.size(); j++) {
85 DecoderInfo info = decoders[j];
86 if (StrView(info.mime).equals(mime)) {
87 LOGI("New decoder found for %s (%s)", info.mime, mime);
88 actual_decoder = info;
89 // define output if it has not been defined
90 if (p_print != nullptr &&
91 actual_decoder.decoder->getOutput() == nullptr) {
92 actual_decoder.decoder->setOutput(*p_print);
93 }
94 actual_decoder.decoder->begin();
95 result = true;
96 }
97 }
98 is_first = false;
99 return result;
100 }
101
102 size_t write(const uint8_t* data, size_t len) override {
103 if (is_first) {
104 const char* mime = nullptr;
105 if (p_url_stream != nullptr) {
106 // get content type from http header
107 mime = p_url_stream->getReplyHeader(CONTENT_TYPE);
108 if (mime) LOGI("mime from http request: %s", mime);
109 }
110 if (mime == nullptr) {
111 // use the mime detector
112 mime_detector.write((uint8_t*)data, len);
113 mime = mime_detector.mime();
114 if (mime) LOGI("mime from mime_detector: %s", mime);
115 }
116 if (mime != nullptr) {
117 // select the decoder based on the detemined mime type
118 if (!selectDecoder(mime)) {
119 LOGE("The decoder could not be found for %s", mime);
120 actual_decoder.decoder = &nop;
121 actual_decoder.is_open = true;
122 }
123 }
124 is_first = false;
125 }
126 // check if we have a decoder
127 if (actual_decoder.decoder == nullptr) return 0;
128 // decode the data
129 return actual_decoder.decoder->write(data, len);
130 }
131
132 virtual operator bool() override {
133 if (actual_decoder.decoder == &nop) return false;
134 return is_first || actual_decoder.is_open;
135 };
136
137 protected:
138 struct DecoderInfo {
139 const char* mime = nullptr;
140 AudioDecoder* decoder = nullptr;
141 bool is_open = false;
142 DecoderInfo() = default;
143 DecoderInfo(const char* mime, AudioDecoder* decoder) {
144 this->mime = mime;
145 this->decoder = decoder;
146 }
147 } actual_decoder;
148 Vector<DecoderInfo> decoders{0};
149 MimeDetector mime_detector;
150 CodecNOP nop;
151 AbstractURLStream* p_url_stream = nullptr;
152 bool is_first = true;
153};
154
155} // namespace audio_tools
Abstract Base class for all URLStream implementations.
Definition AbstractURLStream.h:17
virtual const char * getReplyHeader(const char *header)=0
Provides reply header information.
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition AudioCodecsBase.h:36
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:151
Dummy no implmentation Codec. This is used so that we can initialize some pointers to decoders and en...
Definition AudioCodecsBase.h:124
Logic to detemine the mime type from the content. By default the following mime types are supported (...
Definition MimeDetector.h:23
void setCheck(const char *mime, bool(*check)(uint8_t *start, size_t len))
adds/updates the checking logic for the indicated mime
Definition MimeDetector.h:47
size_t write(uint8_t *data, size_t len)
write the header to determine the mime
Definition MimeDetector.h:40
const char * mime()
Definition MimeDetector.h:68
Manage multiple decoders: the actual decoder is only opened when it has been selected....
Definition MultiDecoder.h:21
MultiDecoder()=default
Default constructor.
bool selectDecoder(const char *mime)
Definition MultiDecoder.h:73
void addDecoder(AudioDecoder &decoder, const char *mime, bool(*check)(uint8_t *data, size_t len))
Definition MultiDecoder.h:55
void setMimeSource(AbstractURLStream &url)
Defines url stream from which we determine the mime type from the reply header.
Definition MultiDecoder.h:69
void end() override
closes the actual decoder
Definition MultiDecoder.h:36
void addDecoder(AudioDecoder &decoder, const char *mime)
Adds a decoder that will be selected by it's mime type.
Definition MultiDecoder.h:47
MultiDecoder(AbstractURLStream &url)
Provides a URLStream to look up the mime type from the http reply header.
Definition MultiDecoder.h:26
bool begin() override
Enables the automatic mime type determination.
Definition MultiDecoder.h:29
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition MultiDecoder.h:61
Definition NoArduino.h:62
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition StrView.h:165
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Definition MultiDecoder.h:138