• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 
13 #include "iamf/cli/codec/flac_decoder.h"
14 
15 #include <algorithm>
16 #include <cstddef>
17 #include <cstdint>
18 #include <vector>
19 
20 #include "absl/log/log.h"
21 #include "absl/status/status.h"
22 #include "absl/strings/str_cat.h"
23 #include "iamf/cli/codec/decoder_base.h"
24 #include "include/FLAC/format.h"
25 #include "include/FLAC/ordinals.h"
26 #include "include/FLAC/stream_decoder.h"
27 
28 namespace iamf_tools {
29 
LibFlacReadCallback(const FLAC__StreamDecoder *,FLAC__byte buffer[],size_t * bytes,void * client_data)30 FLAC__StreamDecoderReadStatus FlacDecoder::LibFlacReadCallback(
31     const FLAC__StreamDecoder* /*decoder*/, FLAC__byte buffer[], size_t* bytes,
32     void* client_data) {
33   auto flac_decoder = static_cast<FlacDecoder*>(client_data);
34   auto encoded_frame = flac_decoder->GetEncodedFrame();
35   if (encoded_frame.empty()) {
36     // No more data to read.
37     *bytes = 0;
38     return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
39   }
40   if (encoded_frame.size() > *bytes) {
41     LOG(ERROR) << "Encoded frame size " << encoded_frame.size()
42                << " is larger than the libflac buffer size " << *bytes;
43     *bytes = 0;
44     return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
45   }
46   for (int i = 0; i < encoded_frame.size(); ++i) {
47     buffer[i] = encoded_frame[i];
48   }
49   *bytes = encoded_frame.size();
50   return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
51 }
52 
LibFlacWriteCallback(const FLAC__StreamDecoder *,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)53 FLAC__StreamDecoderWriteStatus FlacDecoder::LibFlacWriteCallback(
54     const FLAC__StreamDecoder* /*decoder*/, const FLAC__Frame* frame,
55     const FLAC__int32* const buffer[], void* client_data) {
56   auto* flac_decoder = static_cast<FlacDecoder*>(client_data);
57   const auto num_samples_per_channel = frame->header.blocksize;
58   if (flac_decoder->GetNumSamplesPerChannel() != frame->header.blocksize) {
59     LOG(ERROR) << "Frame blocksize " << frame->header.blocksize
60                << " does not match expected number of samples per channel "
61                << flac_decoder->GetNumSamplesPerChannel();
62     return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
63   }
64   std::vector<std::vector<int32_t>> decoded_samples(
65       num_samples_per_channel, std::vector<int32_t>(frame->header.channels));
66   // Note: libFLAC represents data in a planar fashion, so each channel is
67   // stored in a separate array, and the elements within those arrays represent
68   // time ticks. However, we store samples in an interleaved fashion, which
69   // means that each outer entry in decoded_samples represents a time tick, and
70   // each element within represents a channel. So we need to transpose the data
71   // from libFLAC's planar format into our interleaved format.
72   for (int c = 0; c < frame->header.channels; ++c) {
73     const FLAC__int32* const channel_buffer = buffer[c];
74     for (int t = 0; t < num_samples_per_channel; ++t) {
75       decoded_samples[t][c] = channel_buffer[t]
76                               << (32 - frame->header.bits_per_sample);
77     }
78   }
79   flac_decoder->SetDecodedFrame(decoded_samples);
80   return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
81 }
82 
LibFlacErrorCallback(const FLAC__StreamDecoder *,FLAC__StreamDecoderErrorStatus status,void *)83 void FlacDecoder::LibFlacErrorCallback(const FLAC__StreamDecoder* /*decoder*/,
84                                        FLAC__StreamDecoderErrorStatus status,
85                                        void* /*client_data*/) {
86   switch (status) {
87     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
88       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC";
89       break;
90     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
91       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER";
92       break;
93     case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
94       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH";
95       break;
96     case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
97       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM";
98       break;
99     default:
100       LOG(ERROR) << "Unknown FLAC__StreamDecoderErrorStatus= " << status;
101       break;
102   }
103 }
104 
FlacDecoder(int num_channels,uint32_t num_samples_per_frame)105 FlacDecoder::FlacDecoder(int num_channels, uint32_t num_samples_per_frame)
106     : DecoderBase(num_channels, num_samples_per_frame) {}
107 
~FlacDecoder()108 FlacDecoder::~FlacDecoder() {
109   if (decoder_ != nullptr) {
110     FLAC__stream_decoder_delete(decoder_);
111   }
112 }
113 
Initialize()114 absl::Status FlacDecoder::Initialize() {
115   decoder_ = FLAC__stream_decoder_new();
116   if (decoder_ == nullptr) {
117     return absl::InternalError("Failed to create FLAC stream decoder.");
118   }
119   FLAC__StreamDecoderInitStatus status = FLAC__stream_decoder_init_stream(
120       decoder_, LibFlacReadCallback, /*seek_callback=*/nullptr,
121       /*tell_callback=*/nullptr, /*length_callback=*/nullptr,
122       /*eof_callback=*/nullptr, LibFlacWriteCallback,
123       /*metadata_callback=*/nullptr, LibFlacErrorCallback,
124       static_cast<void*>(this));
125 
126   if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
127     return absl::InternalError(
128         absl::StrCat("Failed to initialize FLAC stream decoder: ", status));
129   }
130   return absl::OkStatus();
131 }
132 
Finalize()133 absl::Status FlacDecoder::Finalize() {
134   // Signal to `libflac` the decoder is finished.
135   if (!FLAC__stream_decoder_finish(decoder_)) {
136     return absl::InternalError("Failed to finalize Flac stream decoder.");
137   }
138   return absl::OkStatus();
139 }
140 
DecodeAudioFrame(const std::vector<uint8_t> & encoded_frame)141 absl::Status FlacDecoder::DecodeAudioFrame(
142     const std::vector<uint8_t>& encoded_frame) {
143   num_valid_ticks_ = 0;
144 
145   // Set the encoded frame to be decoded; the libflac decoder will copy the
146   // data using LibFlacReadCallback.
147   encoded_frame_ = encoded_frame;
148   if (!FLAC__stream_decoder_process_single(decoder_)) {
149     // More specific error information is logged in LibFlacErrorCallback.
150     return absl::InternalError("Failed to decode FLAC frame.");
151   }
152   // Get the decoded frame, which will have been set by LibFlacWriteCallback.
153   // Copy the first `num_valid_ticks_` time samples to `decoded_samples_`.
154   num_valid_ticks_ = decoded_frame_.size();
155   std::copy(decoded_frame_.begin(), decoded_frame_.begin() + num_valid_ticks_,
156             decoded_samples_.begin());
157   return absl::OkStatus();
158 }
159 
160 }  // namespace iamf_tools
161