88
99namespace audio_tools {
1010
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-
10411/* *
10512 * @brief A Streaming Decoder where we provide both the input and output
10613 * as streams.
@@ -821,8 +728,7 @@ class MultiStreamingDecoder : public StreamingDecoder {
821728 nullptr ; // /< Optional MIME source for custom logic
822729 Stream *p_data_source = nullptr ; // /< effective data source for decoder
823730
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
826732 const char * toStr (const char * str){
827733 return str == nullptr ? " " : str;
828734 }
@@ -872,15 +778,16 @@ class MultiStreamingDecoder : public StreamingDecoder {
872778 p_data_source = p_input;
873779 } else {
874780 // 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
875783 assert (p_input != nullptr );
784+ buffered_stream.setStream (*p_input);
785+ buffered_stream.resize (DEFAULT_BUFFER_SIZE);
786+ p_data_source = &buffered_stream;
876787
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
880789 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
884791 if (bytesRead == 0 ) return false ;
885792
886793 // Feed the sample data to the MIME detector for format analysis
@@ -889,10 +796,6 @@ class MultiStreamingDecoder : public StreamingDecoder {
889796 mime = mime_detector.mime ();
890797 LOGI (" mime from detector: %s" , toStr (mime));
891798
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;
896799 }
897800
898801 // Process the detected/provided MIME type
0 commit comments