---------------------------------------------------------------------------
| 102 | |
| 103 | // --------------------------------------------------------------------------- |
| 104 | bool AudioReader::load_audio_from_memory(const uint8_t* data, size_t size, |
| 105 | audio_data_t& out_audio, |
| 106 | int target_sample_rate, |
| 107 | MonoDownmixMode downmix) |
| 108 | { |
| 109 | init_ffmpeg_once(); |
| 110 | |
| 111 | if (!data || size == 0) { |
| 112 | std::cerr << "Error: empty audio buffer" << std::endl; |
| 113 | return false; |
| 114 | } |
| 115 | |
| 116 | constexpr int kAVIOBufSize = 32768; |
| 117 | auto* avio_buf = static_cast<uint8_t*>(av_malloc(kAVIOBufSize)); |
| 118 | if (!avio_buf) { |
| 119 | std::cerr << "Error: could not allocate AVIO buffer" << std::endl; |
| 120 | return false; |
| 121 | } |
| 122 | |
| 123 | MemoryIOContext mem_ctx{data, size, 0}; |
| 124 | AVIOContext* avio_ctx = avio_alloc_context(avio_buf, kAVIOBufSize, 0, |
| 125 | &mem_ctx, mem_read_packet, nullptr, mem_seek); |
| 126 | if (!avio_ctx) { |
| 127 | av_free(avio_buf); |
| 128 | std::cerr << "Error: could not create AVIO context" << std::endl; |
| 129 | return false; |
| 130 | } |
| 131 | |
| 132 | AVFormatContext* format_ctx = avformat_alloc_context(); |
| 133 | if (!format_ctx) { |
| 134 | avio_context_free(&avio_ctx); |
| 135 | std::cerr << "Error: could not allocate AVFormatContext" << std::endl; |
| 136 | return false; |
| 137 | } |
| 138 | format_ctx->pb = avio_ctx; |
| 139 | |
| 140 | if (avformat_open_input(&format_ctx, nullptr, nullptr, nullptr) < 0) { |
| 141 | // avformat_open_input frees format_ctx on failure |
| 142 | avio_context_free(&avio_ctx); |
| 143 | std::cerr << "Error: could not open audio from memory buffer" << std::endl; |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | bool ok = decode_audio(format_ctx, out_audio, target_sample_rate, downmix); |
| 148 | avformat_close_input(&format_ctx); |
| 149 | avio_context_free(&avio_ctx); |
| 150 | return ok; |
| 151 | } |
| 152 | |
| 153 | // --------------------------------------------------------------------------- |
| 154 | // Core decode + resample logic (shared by file and memory paths) |
no test coverage detected