Skip to content

Commit

Permalink
Add write callback function in flac decoder stream callbacks.
Browse files Browse the repository at this point in the history
Also adds the requisite getters and setters in FlacDecoder.

PiperOrigin-RevId: 686681700
  • Loading branch information
Googler authored and jwcullen committed Oct 18, 2024
1 parent 52aba1a commit 309e6eb
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
17 changes: 17 additions & 0 deletions iamf/cli/codec/flac_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,25 @@ class FlacDecoder : public DecoderBase {
*/
std::vector<uint8_t> GetEncodedFrame() const { return encoded_frame_; }

/*!\brief Sets a decoded FLAC frame in decoder.decoded_frame_.
*
* \param decoded_frame Decoded FLAC frame.
*/
void SetDecodedFrame(const std::vector<std::vector<int32_t>>& decoded_frame) {
decoded_frame_ = decoded_frame;
}

/*!\brief Retrieves the decoded FLAC frame in decoder.decoded_frame_.
*
* \return Vector of decoded FLAC samples.
*/
std::vector<std::vector<int32_t>> GetDecodedFrame() const {
return decoded_frame_;
}

private:
std::vector<uint8_t> encoded_frame_ = {};
std::vector<std::vector<int32_t>> decoded_frame_ = {};
const FlacDecoderConfig decoder_config_;
};

Expand Down
22 changes: 22 additions & 0 deletions iamf/cli/codec/flac_decoder_stream_callbacks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
#include "iamf/cli/codec/flac_decoder_stream_callbacks.h"

#include <cstddef>
#include <cstdint>
#include <vector>

#include "absl/log/log.h"
#include "iamf/cli/codec/flac_decoder.h"
#include "include/FLAC/format.h"
#include "include/FLAC/ordinals.h"
#include "include/FLAC/stream_decoder.h"

Expand Down Expand Up @@ -44,4 +47,23 @@ FLAC__StreamDecoderReadStatus LibFlacReadCallback(
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}

FLAC__StreamDecoderWriteStatus LibFlacWriteCallback(
const FLAC__StreamDecoder* /*decoder*/, const FLAC__Frame* frame,
const FLAC__int32* const buffer[], void* client_data) {
std::vector<std::vector<int32_t>> decoded_samples(frame->header.channels);
auto* flac_decoder = static_cast<FlacDecoder*>(client_data);
const auto num_samples_per_channel = frame->header.blocksize;
// Note: libFLAC represents data in a planar fashion, so each channel is
// stored in a separate array.
for (int i = 0; i < frame->header.channels; ++i) {
decoded_samples[i].resize(num_samples_per_channel);
const FLAC__int32* const channel_buffer = buffer[i];
for (int j = 0; j < num_samples_per_channel; ++j) {
decoded_samples[i][j] = static_cast<int32_t>(channel_buffer[j]);
}
}
flac_decoder->SetDecodedFrame(decoded_samples);
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}

} // namespace iamf_tools
23 changes: 23 additions & 0 deletions iamf/cli/codec/flac_decoder_stream_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <cstddef>

#include "include/FLAC/format.h"
#include "include/FLAC/ordinals.h"
#include "include/FLAC/stream_decoder.h"

Expand All @@ -38,6 +39,28 @@ FLAC__StreamDecoderReadStatus LibFlacReadCallback(
const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes,
void* client_data);

/*!\brief Writes a decoded flac frame to an instance of FlacDecoder.
*
* This callback function is used to write out a decoded frame from the libflac
* decoder.
*
* \param decoder Unused libflac stream decoder. This parameter is not used in
* this implementation, but is included to override the libflac
* signature.
* \param frame libflac encoded frame metadata.
* \param buffer Array of pointers to decoded channels of data. Each pointer
* will point to an array of signed samples of length
* `frame->header.blocksize`. Channels will be ordered according to the
* FLAC specification.
* \param client_data Universal pointer, which in this case should point to
* FlacDecoder.
*
* \return A libflac write status indicating whether the write was successful.
*/
FLAC__StreamDecoderWriteStatus LibFlacWriteCallback(
const FLAC__StreamDecoder* /*decoder*/, const FLAC__Frame* frame,
const FLAC__int32* const buffer[], void* client_data);

} // namespace iamf_tools

#endif // CLI_CODEC_FLAC_DECODER_STREAM_CALLBACKS_H_
33 changes: 33 additions & 0 deletions iamf/cli/codec/tests/flac_decoder_stream_callbacks_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "iamf/obu/codec_config.h"
#include "iamf/obu/decoder_config/flac_decoder_config.h"
#include "iamf/obu/obu_header.h"
#include "include/FLAC/format.h"
#include "include/FLAC/ordinals.h"
#include "include/FLAC/stream_decoder.h"

Expand Down Expand Up @@ -76,5 +77,37 @@ TEST_F(FlacDecoderStreamCallbacksTest, ReadCallbackSuccess) {
EXPECT_THAT(buffer, ElementsAreArray(encoded_frame));
}

TEST_F(FlacDecoderStreamCallbacksTest, WriteCallbackSuccess32BitSamples) {
FLAC__Frame frame;
frame.header.channels = 2;
frame.header.blocksize = 3;
frame.header.bits_per_sample = 32;
FLAC__int32 channel_0[] = {1, 0x7fffffff, 3};
FLAC__int32 channel_1[] = {2, 3, 4};
const FLAC__int32 *const buffer[] = {channel_0, channel_1};
auto status = LibFlacWriteCallback(/*stream_decoder=*/nullptr, &frame, buffer,
&flac_decoder_);
EXPECT_EQ(status, FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE);
EXPECT_THAT(flac_decoder_.GetDecodedFrame(),
ElementsAreArray(std::vector<std::vector<int32_t>>(
{{1, 0x7fffffff, 3}, {2, 3, 4}})));
}

TEST_F(FlacDecoderStreamCallbacksTest, WriteCallbackSuccess16BitSamples) {
FLAC__Frame frame;
frame.header.channels = 2;
frame.header.blocksize = 2;
frame.header.bits_per_sample = 16;
FLAC__int32 channel_0[] = {0x11110000, 0x7fff0000};
FLAC__int32 channel_1[] = {0x01010000, 0x22220000};
const FLAC__int32 *const buffer[] = {channel_0, channel_1};
auto status = LibFlacWriteCallback(/*stream_decoder=*/nullptr, &frame, buffer,
&flac_decoder_);
EXPECT_EQ(status, FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE);
EXPECT_THAT(flac_decoder_.GetDecodedFrame(),
ElementsAreArray(std::vector<std::vector<int32_t>>(
{{0x11110000, 0x7fff0000}, {0x01010000, 0x22220000}})));
}

} // namespace
} // namespace iamf_tools

0 comments on commit 309e6eb

Please sign in to comment.