From a3dc6bb5a165cc448e45dc9812686f7834462870 Mon Sep 17 00:00:00 2001 From: badaix Date: Wed, 23 Dec 2015 08:20:21 +0100 Subject: [PATCH] fixed FLAC playback timing --- client/decoder/flacDecoder.cpp | 77 +++++++++++++++++----------------- client/decoder/flacDecoder.h | 21 ++++++++++ message/message.h | 17 ++------ 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/client/decoder/flacDecoder.cpp b/client/decoder/flacDecoder.cpp index 937bbfd3..c267b3b4 100644 --- a/client/decoder/flacDecoder.cpp +++ b/client/decoder/flacDecoder.cpp @@ -16,13 +16,14 @@ along with this program. If not, see . ***/ -#include "flacDecoder.h" #include #include #include #include +#include "flacDecoder.h" #include "common/log.h" + using namespace std; @@ -53,18 +54,26 @@ FlacDecoder::~FlacDecoder() bool FlacDecoder::decode(msg::PcmChunk* chunk) { + cacheInfo_.reset(); pcmChunk = chunk; -//logO << "Decode start: " << chunk->payloadSize << endl; flacChunk->payload = (char*)realloc(flacChunk->payload, chunk->payloadSize); memcpy(flacChunk->payload, chunk->payload, chunk->payloadSize); flacChunk->payloadSize = chunk->payloadSize; pcmChunk->payload = (char*)realloc(pcmChunk->payload, 0); pcmChunk->payloadSize = 0; - FLAC__stream_decoder_process_single(decoder); - if (flacChunk->payloadSize > 0) + while (flacChunk->payloadSize > 0) FLAC__stream_decoder_process_single(decoder); -//logO << "Decode end\n" << endl; + + if ((cacheInfo_.cachedBlocks_ > 0) && (cacheInfo_.sampleRate_ != 0)) + { + double diffMs = cacheInfo_.cachedBlocks_ / ((double)cacheInfo_.sampleRate_ / 1000.); + int32_t s = (diffMs / 1000); + int32_t us = (diffMs * 1000); + us %= 1000000; + logD << "Cached: " << cacheInfo_.cachedBlocks_ << ", " << diffMs << "ms, " << s << "s, " << us << "us\n"; + chunk->timestamp = chunk->timestamp - tv(s, us); + } return true; } @@ -75,21 +84,19 @@ bool FlacDecoder::setHeader(msg::Header* chunk) FLAC__bool ok = true; FLAC__StreamDecoderInitStatus init_status; - if((decoder = FLAC__stream_decoder_new()) == NULL) { - fprintf(stderr, "ERROR: allocating decoder\n"); - return 1; + if ((decoder = FLAC__stream_decoder_new()) == NULL) + { + logS(kLogErr) << "ERROR: allocating decoder\n"; + return false; } // (void)FLAC__stream_decoder_set_md5_checking(decoder, true); - init_status = FLAC__stream_decoder_init_stream(decoder, read_callback, NULL, NULL, NULL, NULL, write_callback, metadata_callback, error_callback, this); - -// init_status = FLAC__stream_decoder_init_file(decoder, argv[1], write_callback, metadata_callback, error_callback, fout); - if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { - fprintf(stderr, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]); + if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) + { + logS(kLogErr) << "ERROR: initializing decoder: " << FLAC__StreamDecoderInitStatusString[init_status] << "\n"; ok = false; } -// FLAC__stream_decoder_process_until_end_of_stream(decoder); FLAC__stream_decoder_process_until_end_of_metadata(decoder); return ok; @@ -106,23 +113,14 @@ FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, } else if (flacChunk != NULL) { -//logO << "Read: " << *bytes << "\t" << flacChunk->payloadSize << "\n"; - FLAC__StreamDecoderReadStatus result = FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + ((FlacDecoder*)client_data)->cacheInfo_.isCachedChunk_ = false; if (*bytes > flacChunk->payloadSize) *bytes = flacChunk->payloadSize; -// else -// result = FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - -// if (flacChunk->payloadSize == 0) -// return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; memcpy(buffer, flacChunk->payload, *bytes); memmove(flacChunk->payload, flacChunk->payload + *bytes, flacChunk->payloadSize - *bytes); flacChunk->payloadSize = flacChunk->payloadSize - *bytes; flacChunk->payload = (char*)realloc(flacChunk->payload, flacChunk->payloadSize); -//logO << "Read end\n"; -// return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - return result; } return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } @@ -130,7 +128,6 @@ FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) { -//logO << "Write start\n"; (void)decoder; /* if(channels != 2 || bps != 16) { @@ -141,30 +138,34 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder fprintf(stderr, "ERROR: This frame contains %d channels (should be 2)\n", frame->header.channels); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } -*/ if(buffer [0] == NULL) { - fprintf(stderr, "ERROR: buffer [0] is NULL\n"); +*/ if (buffer[0] == NULL) + { + logS(kLogErr) << "ERROR: buffer [0] is NULL\n"; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } - if(buffer [1] == NULL) { - fprintf(stderr, "ERROR: buffer [1] is NULL\n"); + + if (buffer[1] == NULL) + { + logS(kLogErr) << "ERROR: buffer [1] is NULL\n"; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } if (pcmChunk != NULL) { +//TODO: hard coded to 2 channels, 16 bit size_t bytes = frame->header.blocksize * 4; -//logO << "blocksize: " << frame->header.blocksize << "\tframe_number: " << frame->header.number.frame_number << "\tsample_number: " << frame->header.number.sample_number << "\n"; -//logO << "Write: " << bytes << "\tpayloadSize: " << pcmChunk->payloadSize + bytes << "\n"; -//flacChunk->payloadSize = 0; + + if (((FlacDecoder*)client_data)->cacheInfo_.isCachedChunk_) + ((FlacDecoder*)client_data)->cacheInfo_.cachedBlocks_ += frame->header.blocksize; + pcmChunk->payload = (char*)realloc(pcmChunk->payload, pcmChunk->payloadSize + bytes); - for(size_t i = 0; i < frame->header.blocksize; i++) + for(size_t i = 0; i < frame->header.blocksize; i++) { memcpy(pcmChunk->payload + pcmChunk->payloadSize + 4*i, (char*)(buffer[0] + i), 2); memcpy(pcmChunk->payload + pcmChunk->payloadSize + 4*i+2, (char*)(buffer[1] + i), 2); } pcmChunk->payloadSize += bytes; -//logO << "Write end: " << flacChunk->payloadSize << "\n"; } return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; @@ -173,11 +174,11 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { - (void)decoder, (void)client_data; - + (void)decoder; /* print some stats */ - if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + ((FlacDecoder*)client_data)->cacheInfo_.sampleRate_ = metadata->data.stream_info.sample_rate; logO << "sample rate : " << metadata->data.stream_info.sample_rate << "Hz\n"; logO << "channels : " << metadata->data.stream_info.channels << "\n"; logO << "bits per sample: " << metadata->data.stream_info.bits_per_sample << "\n"; @@ -188,7 +189,7 @@ void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMet void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { (void)decoder, (void)client_data; - fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]); + logS(kLogErr) << "Got error callback: " << FLAC__StreamDecoderErrorStatusString[status] << "\n"; } diff --git a/client/decoder/flacDecoder.h b/client/decoder/flacDecoder.h index 4e7b0849..fef88bac 100644 --- a/client/decoder/flacDecoder.h +++ b/client/decoder/flacDecoder.h @@ -18,8 +18,27 @@ #ifndef FLAC_DECODER_H #define FLAC_DECODER_H + #include "decoder.h" +struct CacheInfo +{ + CacheInfo() : sampleRate_(0) + { + reset(); + } + + void reset() + { + isCachedChunk_ = true; + cachedBlocks_ = 0; + } + + bool isCachedChunk_; + size_t cachedBlocks_; + size_t sampleRate_; +}; + class FlacDecoder : public Decoder { @@ -28,6 +47,8 @@ public: virtual ~FlacDecoder(); virtual bool decode(msg::PcmChunk* chunk); virtual bool setHeader(msg::Header* chunk); + + CacheInfo cacheInfo_; }; diff --git a/message/message.h b/message/message.h index 24a64142..080dac23 100644 --- a/message/message.h +++ b/message/message.h @@ -94,21 +94,12 @@ struct tv tv result(*this); result.sec -= other.sec; result.usec -= other.usec; - if (result.usec > 0) + while (result.usec < 0) { - result.sec += 1; - result.usec = 1000000 - result.usec; + result.sec -= 1; + result.usec += 1000000; } - else if (result.usec < 0) - { - result.usec *= -1; - } - /* else if (result.usec >= 1000000) - { - result.usec -= 1000000; - result.sec += 1; - } - */ return result; + return result; } };