8
8
9
9
namespace audio_tools {
10
10
11
- /* *
12
- * @brief Stream that combines prefix data with original stream
13
- *
14
- * Useful for format detection where some data needs to be preserved.
15
- *
16
- * @ingroup io
17
- * @author Phil Schatzmann
18
- * @copyright GPLv3
19
- */
20
- class PrefixStream : public Stream {
21
- public:
22
- // / Default constructor - call setData() before use
23
- PrefixStream ()
24
- : prefix_data_(nullptr ), prefix_len_(0 ), prefix_pos_(0 ), original_stream_(nullptr ) {}
25
-
26
- // / Constructor with prefix data and original stream
27
- PrefixStream (const uint8_t * prefix_data, size_t prefix_len, Stream& original_stream)
28
- : prefix_data_(prefix_data), prefix_len_(prefix_len), prefix_pos_(0 ), original_stream_(&original_stream) {}
29
-
30
- // / Sets the prefix data and original stream
31
- void setData (const uint8_t * prefix_data, size_t prefix_len, Stream& original_stream) {
32
- prefix_data_ = prefix_data;
33
- prefix_len_ = prefix_len;
34
- prefix_pos_ = 0 ;
35
- original_stream_ = &original_stream;
36
- }
37
-
38
- // / Returns total bytes available (prefix + original stream)
39
- virtual int available () override {
40
- int remaining_prefix = prefix_len_ - prefix_pos_;
41
- if (original_stream_ != nullptr ) {
42
- return remaining_prefix + original_stream_->available ();
43
- }
44
- return remaining_prefix;
45
- }
46
-
47
- // / Reads a single byte
48
- virtual int read () override {
49
- if (prefix_pos_ < prefix_len_) {
50
- return prefix_data_[prefix_pos_++];
51
- }
52
- if (original_stream_ != nullptr ) {
53
- return original_stream_->read ();
54
- }
55
- return -1 ;
56
- }
57
-
58
- // / Peeks at next byte without consuming it
59
- virtual int peek () override {
60
- if (prefix_pos_ < prefix_len_) {
61
- return prefix_data_[prefix_pos_];
62
- }
63
- if (original_stream_ != nullptr ) {
64
- return original_stream_->peek ();
65
- }
66
- return -1 ;
67
- }
68
-
69
- // / Reads multiple bytes into buffer
70
- virtual size_t readBytes (uint8_t * buffer, size_t length) override {
71
- size_t bytes_read = 0 ;
72
-
73
- // First, read from prefix data
74
- if (prefix_pos_ < prefix_len_) {
75
- size_t prefix_available = prefix_len_ - prefix_pos_;
76
- size_t prefix_to_read = (length < prefix_available) ? length : prefix_available;
77
- memcpy (buffer, prefix_data_ + prefix_pos_, prefix_to_read);
78
- prefix_pos_ += prefix_to_read;
79
- bytes_read += prefix_to_read;
80
- buffer += prefix_to_read;
81
- length -= prefix_to_read;
82
- }
83
-
84
- // Then read from original stream if more data is needed
85
- if (length > 0 && original_stream_ != nullptr ) {
86
- bytes_read += original_stream_->readBytes (buffer, length);
87
- }
88
-
89
- return bytes_read;
90
- }
91
-
92
- // / Write operations not supported
93
- virtual size_t write (uint8_t ) override { return 0 ; }
94
- virtual size_t write (const uint8_t *, size_t ) override { return 0 ; }
95
- virtual void flush () override {}
96
-
97
- private:
98
- const uint8_t * prefix_data_; // /< Prefix data buffer
99
- size_t prefix_len_; // /< Length of prefix data
100
- size_t prefix_pos_; // /< Current position in prefix
101
- Stream* original_stream_; // /< Original stream
102
- };
103
-
104
11
/* *
105
12
* @brief A Streaming Decoder where we provide both the input and output
106
13
* as streams.
@@ -821,8 +728,7 @@ class MultiStreamingDecoder : public StreamingDecoder {
821
728
nullptr ; // /< Optional MIME source for custom logic
822
729
Stream *p_data_source = nullptr ; // /< effective data source for decoder
823
730
824
- PrefixStream prefix_stream; // /< Instance of prefix stream (uses placement new on prefix_stream_storage)
825
-
731
+ BufferedStream buffered_stream{0 }; // /< Buffered stream for data preservation
826
732
const char * toStr (const char * str){
827
733
return str == nullptr ? " " : str;
828
734
}
@@ -872,15 +778,16 @@ class MultiStreamingDecoder : public StreamingDecoder {
872
778
p_data_source = p_input;
873
779
} else {
874
780
// Option 2: Auto-detect MIME type by analyzing stream content
781
+ // Redirect the decoder to use the buffered stream
782
+ // we use the buffered stream as input
875
783
assert (p_input != nullptr );
784
+ buffered_stream.setStream (*p_input);
785
+ buffered_stream.resize (DEFAULT_BUFFER_SIZE);
786
+ p_data_source = &buffered_stream;
876
787
877
- // Read a sample of data for MIME detection
878
- // Allocate buffer for MIME detection sample (160 bytes is sufficient
879
- // for most audio format headers to be identified)
788
+ // This requires reading a sample of data to identify the format
880
789
detection_buffer.resize (160 );
881
- size_t bytesRead = p_input->readBytes (detection_buffer.data (), detection_buffer.size ());
882
-
883
- // If no data is available, we cannot proceed with detection
790
+ size_t bytesRead = buffered_stream.peekBytes (detection_buffer.data (), detection_buffer.size ()); // If no data is available, we cannot proceed with detection
884
791
if (bytesRead == 0 ) return false ;
885
792
886
793
// Feed the sample data to the MIME detector for format analysis
@@ -889,10 +796,6 @@ class MultiStreamingDecoder : public StreamingDecoder {
889
796
mime = mime_detector.mime ();
890
797
LOGI (" mime from detector: %s" , toStr (mime));
891
798
892
- // Create a prefix stream that combines the detection data with the original stream
893
- // This ensures the decoder receives the complete stream including the bytes used for detection
894
- prefix_stream.setData (detection_buffer.data (), bytesRead, *p_input);
895
- p_data_source = &prefix_stream;
896
799
}
897
800
898
801
// Process the detected/provided MIME type
0 commit comments