204 lines
5.8 KiB
C++
204 lines
5.8 KiB
C++
|
#include"mkv_flac_decoder.h"
|
||
|
#include "main.h"
|
||
|
|
||
|
static FLAC__StreamDecoderReadStatus Packet_Read(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
|
||
|
{
|
||
|
packet_client_data_t packet = (packet_client_data_t)client_data;
|
||
|
size_t to_copy = *bytes;
|
||
|
if (to_copy > packet->buffer_length) {
|
||
|
to_copy = packet->buffer_length;
|
||
|
}
|
||
|
memcpy(buffer, packet->buffer, to_copy);
|
||
|
*bytes = to_copy;
|
||
|
packet->buffer += to_copy;
|
||
|
packet->buffer_length -= to_copy;
|
||
|
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||
|
}
|
||
|
|
||
|
static FLAC__StreamDecoderSeekStatus Packet_Seek(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||
|
{
|
||
|
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
static FLAC__StreamDecoderTellStatus Packet_Tell(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||
|
{
|
||
|
return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
static FLAC__StreamDecoderLengthStatus Packet_Length(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||
|
{
|
||
|
return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
static FLAC__bool Packet_EOF(const FLAC__StreamDecoder *decoder, void *client_data)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void OnError(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||
|
{
|
||
|
//client_data=client_data; // dummy line so i can set a breakpoint
|
||
|
}
|
||
|
|
||
|
static void OnMetadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||
|
{
|
||
|
packet_client_data_t packet = (packet_client_data_t)client_data;
|
||
|
switch(metadata->type)
|
||
|
{
|
||
|
case FLAC__METADATA_TYPE_STREAMINFO:
|
||
|
{
|
||
|
packet->frame_size = metadata->data.stream_info.max_blocksize;
|
||
|
packet->bps=metadata->data.stream_info.bits_per_sample;
|
||
|
packet->bytes_per_sample = (packet->bps + 7) / 8;
|
||
|
packet->channels=metadata->data.stream_info.channels;
|
||
|
packet->sample_rate=metadata->data.stream_info.sample_rate;
|
||
|
packet->samples=metadata->data.stream_info.total_samples;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static FLAC__StreamDecoderWriteStatus OnAudio(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
|
||
|
{
|
||
|
packet_client_data_t packet = (packet_client_data_t)client_data;
|
||
|
|
||
|
size_t byteLength = packet->bytes_per_sample * packet->channels * frame->header.blocksize;
|
||
|
if (byteLength > packet->outputBufferBytes[0]) {
|
||
|
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||
|
}
|
||
|
InterleaveAndTruncate(buffer, packet->outputBuffer, packet->bytes_per_sample * 8, packet->channels, frame->header.blocksize);
|
||
|
packet->outputBufferBytes[0] = byteLength;
|
||
|
|
||
|
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
MKVFLACDecoder *MKVFLACDecoder::Create(const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels)
|
||
|
{
|
||
|
FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
|
||
|
if (!decoder) {
|
||
|
return 0;
|
||
|
}
|
||
|
packet_client_data_t packet = new packet_client_data_s;
|
||
|
packet->buffer = 0;
|
||
|
packet->buffer_length = 0;
|
||
|
|
||
|
if(FLAC__stream_decoder_init_stream(
|
||
|
decoder,
|
||
|
Packet_Read,
|
||
|
Packet_Seek,
|
||
|
Packet_Tell,
|
||
|
Packet_Length,
|
||
|
Packet_EOF,
|
||
|
OnAudio,
|
||
|
OnMetadata,
|
||
|
OnError,
|
||
|
packet
|
||
|
) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
||
|
{
|
||
|
delete packet;
|
||
|
FLAC__stream_decoder_delete(decoder);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
packet->buffer = (const uint8_t *)track_entry_data->codec_private;
|
||
|
packet->buffer_length = track_entry_data->codec_private_len;
|
||
|
if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
|
||
|
delete packet;
|
||
|
FLAC__stream_decoder_delete(decoder);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
MKVFLACDecoder *mkv_decoder = new MKVFLACDecoder(decoder, packet, preferred_bits);
|
||
|
if (!mkv_decoder) {
|
||
|
delete packet;
|
||
|
FLAC__stream_decoder_delete(decoder);
|
||
|
return 0;
|
||
|
}
|
||
|
return mkv_decoder;
|
||
|
}
|
||
|
|
||
|
MKVFLACDecoder::MKVFLACDecoder(FLAC__StreamDecoder *decoder, packet_client_data_t packet, unsigned int bps)
|
||
|
: decoder(decoder), packet(packet), bps(bps)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
MKVFLACDecoder::~MKVFLACDecoder()
|
||
|
{
|
||
|
delete packet;
|
||
|
FLAC__stream_decoder_delete(decoder);
|
||
|
}
|
||
|
|
||
|
int MKVFLACDecoder::OutputFrameSize(size_t *frame_size)
|
||
|
{
|
||
|
*frame_size = packet->frame_size * packet->bytes_per_sample * packet->channels;
|
||
|
return MKV_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int MKVFLACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
|
||
|
{
|
||
|
*sampleRate = packet->sample_rate;
|
||
|
*channels = packet->channels;
|
||
|
*bitsPerSample = packet->bps;
|
||
|
*isFloat = false;
|
||
|
|
||
|
return MKV_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int MKVFLACDecoder::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
|
||
|
{
|
||
|
packet->buffer = (const uint8_t *)inputBuffer;
|
||
|
packet->buffer_length = inputBufferBytes;
|
||
|
|
||
|
packet->outputBuffer = outputBuffer;
|
||
|
packet->outputBufferBytes = outputBufferBytes;
|
||
|
|
||
|
if (FLAC__stream_decoder_process_single(decoder) == 0) {
|
||
|
return MKV_FAILURE;
|
||
|
}
|
||
|
|
||
|
return MKV_SUCCESS;
|
||
|
}
|
||
|
|
||
|
void MKVFLACDecoder::Flush()
|
||
|
{
|
||
|
FLAC__stream_decoder_flush(decoder);
|
||
|
}
|
||
|
|
||
|
void MKVFLACDecoder::Close()
|
||
|
{
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
#define CBCLASS MKVFLACDecoder
|
||
|
START_DISPATCH;
|
||
|
CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
|
||
|
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
|
||
|
CB(DECODE_BLOCK, DecodeBlock)
|
||
|
VCB(FLUSH, Flush)
|
||
|
VCB(CLOSE, Close)
|
||
|
END_DISPATCH;
|
||
|
#undef CBCLASS
|
||
|
|
||
|
|
||
|
int MKVDecoder::CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels,bool floating_point, ifc_mkvaudiodecoder **decoder)
|
||
|
{
|
||
|
if (!strcmp(codec_id, "A_FLAC"))
|
||
|
{
|
||
|
MKVFLACDecoder *flac_decoder = MKVFLACDecoder::Create(track_entry_data, audio_data, preferred_bits, max_channels);
|
||
|
if (flac_decoder)
|
||
|
{
|
||
|
*decoder = flac_decoder;
|
||
|
return CREATEDECODER_SUCCESS;
|
||
|
}
|
||
|
return CREATEDECODER_FAILURE;
|
||
|
}
|
||
|
|
||
|
return CREATEDECODER_NOT_MINE;
|
||
|
}
|
||
|
|
||
|
#define CBCLASS MKVDecoder
|
||
|
START_DISPATCH;
|
||
|
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
|
||
|
END_DISPATCH;
|
||
|
#undef CBCLASS
|