From af0a2436fc2465edb844f4ba5376a8c05c4e19ad Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sat, 11 Jun 2022 06:39:00 -0700 Subject: [PATCH] [FFMPEG Input] Support reading more metadata Now read all metadata and signal it, and also support pre-buffering a small block of sample frames if there is embedded artwork, since the embedded artwork must be handled by the sample decode function. Signed-off-by: Christopher Snowhill --- Plugins/FFMPEG/FFMPEGDecoder.h | 5 +++++ Plugins/FFMPEG/FFMPEGDecoder.m | 41 +++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Plugins/FFMPEG/FFMPEGDecoder.h b/Plugins/FFMPEG/FFMPEGDecoder.h index a817c4f61..ece485ad1 100644 --- a/Plugins/FFMPEG/FFMPEGDecoder.h +++ b/Plugins/FFMPEG/FFMPEGDecoder.h @@ -35,6 +35,11 @@ AVFrame *lastDecodedFrame; AVPacket *lastReadPacket; + BOOL metadataUpdated; + + int prebufferedAudio; + uint8_t *prebufferedAudioData; + BOOL rawDSD; BOOL rawDSDReverseBits; BOOL rawDSDPlanar; diff --git a/Plugins/FFMPEG/FFMPEGDecoder.m b/Plugins/FFMPEG/FFMPEGDecoder.m index 5bc42c975..b016f36b3 100644 --- a/Plugins/FFMPEG/FFMPEGDecoder.m +++ b/Plugins/FFMPEG/FFMPEGDecoder.m @@ -462,8 +462,23 @@ static uint8_t reverse_bits[0x100]; replayGainTrackPeak = 0.0; albumArt = [NSData data]; id3Metadata = @{}; + metadataUpdated = NO; [self updateMetadata]; + prebufferedAudio = 0; + prebufferedAudioData = NULL; + + if(attachedPicIndex >= 0) { + int frameSize = rawDSD ? channels : channels * (bitsPerSample / 8); + prebufferedAudioData = malloc(1024 * frameSize); + [self readAudio:prebufferedAudioData frames:1024]; + } + + if(metadataUpdated) { + [self willChangeValueForKey:@"metadata"]; + [self didChangeValueForKey:@"metadata"]; + } + return YES; } @@ -608,6 +623,8 @@ static uint8_t reverse_bits[0x100]; if(![source seekable]) { [self willChangeValueForKey:@"metadata"]; [self didChangeValueForKey:@"metadata"]; + } else { + metadataUpdated = YES; } } } @@ -632,19 +649,35 @@ static uint8_t reverse_bits[0x100]; if(![source seekable]) { [self willChangeValueForKey:@"metadata"]; [self didChangeValueForKey:@"metadata"]; + } else { + metadataUpdated = YES; } } } - (int)readAudio:(void *)buf frames:(UInt32)frames { + int frameSize = rawDSD ? channels : channels * (bitsPerSample / 8); + int bytesToRead = frames * frameSize; + int bytesRead = 0; + + if(prebufferedAudio) { + // A bit of ignored read-ahead to support embedded artwork + int bytesBuffered = prebufferedAudio * frameSize; + int bytesToCopy = (bytesBuffered > bytesToRead) ? bytesToRead : bytesBuffered; + memcpy(buf, prebufferedAudioData, bytesToCopy); + memmove(prebufferedAudioData, prebufferedAudioData + bytesToCopy, bytesBuffered - bytesToCopy); + prebufferedAudio -= bytesToCopy / frameSize; + bytesRead = bytesToCopy; + + int framesReadNow = bytesRead / frameSize; + framesRead -= framesReadNow; + } + if(totalFrames && framesRead >= totalFrames) return 0; - int frameSize = rawDSD ? channels : channels * (bitsPerSample / 8); int dataSize = 0; - int bytesToRead = frames * frameSize; - int bytesRead = 0; int seekBytesSkip = 0; int errcode; @@ -852,6 +885,8 @@ static uint8_t reverse_bits[0x100]; if(!totalFrames) return -1; + prebufferedAudio = 0; + if(frame >= totalFrames) { framesRead = totalFrames; endOfStream = YES;