• 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_stream_callbacks.h"
14 
15 #include <cstddef>
16 #include <cstdint>
17 #include <vector>
18 
19 #include "absl/log/log.h"
20 #include "iamf/cli/codec/flac_decoder.h"
21 #include "include/FLAC/format.h"
22 #include "include/FLAC/ordinals.h"
23 #include "include/FLAC/stream_decoder.h"
24 
25 namespace iamf_tools {
26 
LibFlacReadCallback(const FLAC__StreamDecoder *,FLAC__byte buffer[],size_t * bytes,void * client_data)27 FLAC__StreamDecoderReadStatus LibFlacReadCallback(
28     const FLAC__StreamDecoder* /*decoder*/, FLAC__byte buffer[], size_t* bytes,
29     void* client_data) {
30   auto flac_decoder = static_cast<FlacDecoder*>(client_data);
31   const auto& encoded_frame = flac_decoder->GetEncodedFrame();
32   if (encoded_frame.empty()) {
33     // No more data to read.
34     *bytes = 0;
35     return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
36   }
37   if (encoded_frame.size() > *bytes) {
38     LOG(ERROR) << "Encoded frame size " << encoded_frame.size()
39                << " is larger than the libflac buffer size " << *bytes;
40     *bytes = 0;
41     return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
42   }
43   for (int i = 0; i < encoded_frame.size(); ++i) {
44     buffer[i] = encoded_frame[i];
45   }
46   *bytes = encoded_frame.size();
47   return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
48 }
49 
LibFlacWriteCallback(const FLAC__StreamDecoder *,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)50 FLAC__StreamDecoderWriteStatus LibFlacWriteCallback(
51     const FLAC__StreamDecoder* /*decoder*/, const FLAC__Frame* frame,
52     const FLAC__int32* const buffer[], void* client_data) {
53   std::vector<std::vector<int32_t>> decoded_samples(frame->header.channels);
54   auto* flac_decoder = static_cast<FlacDecoder*>(client_data);
55   const auto num_samples_per_channel = frame->header.blocksize;
56   // Note: libFLAC represents data in a planar fashion, so each channel is
57   // stored in a separate array.
58   for (int i = 0; i < frame->header.channels; ++i) {
59     decoded_samples[i].resize(num_samples_per_channel);
60     const FLAC__int32* const channel_buffer = buffer[i];
61     for (int j = 0; j < num_samples_per_channel; ++j) {
62       decoded_samples[i][j] = static_cast<int32_t>(channel_buffer[j]);
63     }
64   }
65   flac_decoder->SetDecodedFrame(decoded_samples);
66   return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
67 }
68 
LibFlacErrorCallback(const FLAC__StreamDecoder *,FLAC__StreamDecoderErrorStatus status,void *)69 void LibFlacErrorCallback(const FLAC__StreamDecoder* /*decoder*/,
70                           FLAC__StreamDecoderErrorStatus status,
71                           void* /*client_data*/) {
72   switch (status) {
73     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
74       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC";
75       break;
76     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
77       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER";
78       break;
79     case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
80       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH";
81       break;
82     case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
83       LOG(ERROR) << "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM";
84       break;
85     default:
86       LOG(ERROR) << "Unknown error";
87       break;
88   }
89 }
90 
91 }  // namespace iamf_tools
92