Software aac decoding

This commit is contained in:
Peter 2019-10-19 17:52:07 +04:00
parent 5b889d6367
commit 595284dc9b
7 changed files with 62 additions and 5 deletions

View File

@ -9,6 +9,8 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
private let audioFrame: FFMpegAVFrame private let audioFrame: FFMpegAVFrame
private var resetDecoderOnNextFrame = true private var resetDecoderOnNextFrame = true
private var delayedFrames: [MediaTrackFrame] = []
init(codecContext: FFMpegAVCodecContext) { init(codecContext: FFMpegAVCodecContext) {
self.codecContext = codecContext self.codecContext = codecContext
self.audioFrame = FFMpegAVFrame() self.audioFrame = FFMpegAVFrame()
@ -19,17 +21,59 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
func decode(frame: MediaTrackDecodableFrame) -> MediaTrackFrame? { func decode(frame: MediaTrackDecodableFrame) -> MediaTrackFrame? {
let status = frame.packet.send(toDecoder: self.codecContext) let status = frame.packet.send(toDecoder: self.codecContext)
if status == 0 { if status == 0 {
if self.codecContext.receive(into: self.audioFrame) { while self.codecContext.receive(into: self.audioFrame) {
return convertAudioFrame(self.audioFrame, pts: frame.pts, duration: frame.duration) if let convertedFrame = convertAudioFrame(self.audioFrame, pts: frame.pts, duration: frame.duration) {
self.delayedFrames.append(convertedFrame)
}
}
if self.delayedFrames.count >= 1 {
var minFrameIndex = 0
var minPosition = self.delayedFrames[0].position
for i in 1 ..< self.delayedFrames.count {
if CMTimeCompare(self.delayedFrames[i].position, minPosition) < 0 {
minFrameIndex = i
minPosition = self.delayedFrames[i].position
}
}
return self.delayedFrames.remove(at: minFrameIndex)
} }
} }
return nil return nil
} }
func takeQueuedFrame() -> MediaTrackFrame? {
if self.delayedFrames.count >= 1 {
var minFrameIndex = 0
var minPosition = self.delayedFrames[0].position
for i in 1 ..< self.delayedFrames.count {
if CMTimeCompare(self.delayedFrames[i].position, minPosition) < 0 {
minFrameIndex = i
minPosition = self.delayedFrames[i].position
}
}
return self.delayedFrames.remove(at: minFrameIndex)
} else {
return nil
}
}
func takeRemainingFrame() -> MediaTrackFrame? { func takeRemainingFrame() -> MediaTrackFrame? {
if !self.delayedFrames.isEmpty {
var minFrameIndex = 0
var minPosition = self.delayedFrames[0].position
for i in 1 ..< self.delayedFrames.count {
if CMTimeCompare(self.delayedFrames[i].position, minPosition) < 0 {
minFrameIndex = i
minPosition = self.delayedFrames[i].position
}
}
return self.delayedFrames.remove(at: minFrameIndex)
} else {
return nil return nil
} }
}
private func convertAudioFrame(_ frame: FFMpegAVFrame, pts: CMTime, duration: CMTime) -> MediaTrackFrame? { private func convertAudioFrame(_ frame: FFMpegAVFrame, pts: CMTime, duration: CMTime) -> MediaTrackFrame? {
guard let data = self.swrContext.resample(frame) else { guard let data = self.swrContext.resample(frame) else {

View File

@ -39,6 +39,10 @@ final class FFMpegMediaPassthroughVideoFrameDecoder: MediaTrackFrameDecoder {
return MediaTrackFrame(type: .video, sampleBuffer: sampleBuffer!, resetDecoder: resetDecoder, decoded: false, rotationAngle: self.rotationAngle) return MediaTrackFrame(type: .video, sampleBuffer: sampleBuffer!, resetDecoder: resetDecoder, decoded: false, rotationAngle: self.rotationAngle)
} }
func takeQueuedFrame() -> MediaTrackFrame? {
return nil
}
func takeRemainingFrame() -> MediaTrackFrame? { func takeRemainingFrame() -> MediaTrackFrame? {
return nil return nil
} }

View File

@ -87,6 +87,10 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder {
return nil return nil
} }
public func takeQueuedFrame() -> MediaTrackFrame? {
return nil
}
public func takeRemainingFrame() -> MediaTrackFrame? { public func takeRemainingFrame() -> MediaTrackFrame? {
if !self.delayedFrames.isEmpty { if !self.delayedFrames.isEmpty {
var minFrameIndex = 0 var minFrameIndex = 0

View File

@ -146,6 +146,10 @@ public final class MediaTrackFrameBuffer {
} }
public func takeFrame() -> MediaTrackFrameResult { public func takeFrame() -> MediaTrackFrameResult {
if let decodedFrame = self.decoder.takeQueuedFrame() {
return .frame(decodedFrame)
}
if !self.frames.isEmpty { if !self.frames.isEmpty {
let frame = self.frames.removeFirst() let frame = self.frames.removeFirst()
if let decodedFrame = self.decoder.decode(frame: frame) { if let decodedFrame = self.decoder.decode(frame: frame) {

View File

@ -1,6 +1,7 @@
protocol MediaTrackFrameDecoder { protocol MediaTrackFrameDecoder {
func decode(frame: MediaTrackDecodableFrame) -> MediaTrackFrame? func decode(frame: MediaTrackDecodableFrame) -> MediaTrackFrame?
func takeQueuedFrame() -> MediaTrackFrame?
func takeRemainingFrame() -> MediaTrackFrame? func takeRemainingFrame() -> MediaTrackFrame?
func reset() func reset()
} }

View File

@ -6,7 +6,7 @@
+ (void)initializeGlobals { + (void)initializeGlobals {
#if DEBUG #if DEBUG
av_log_set_level(AV_LOG_ERROR); av_log_set_level(AV_LOG_VERBOSE);
#else #else
av_log_set_level(AV_LOG_QUIET); av_log_set_level(AV_LOG_QUIET);
#endif #endif

View File

@ -55,7 +55,7 @@ CONFIGURE_FLAGS="--enable-cross-compile --disable-programs \
--enable-libopus \ --enable-libopus \
--enable-audiotoolbox \ --enable-audiotoolbox \
--enable-bsf=aac_adtstoasc \ --enable-bsf=aac_adtstoasc \
--enable-decoder=h264,hevc,libopus,mp3_at,aac_at,flac,alac_at,pcm_s16le,pcm_s24le,gsm_ms_at \ --enable-decoder=h264,hevc,libopus,mp3_at,aac,flac,alac_at,pcm_s16le,pcm_s24le,gsm_ms_at \
--enable-demuxer=aac,mov,m4v,mp3,ogg,libopus,flac,wav,aiff,matroska \ --enable-demuxer=aac,mov,m4v,mp3,ogg,libopus,flac,wav,aiff,matroska \
--enable-parser=aac,h264,mp3,libopus \ --enable-parser=aac,h264,mp3,libopus \
--enable-protocol=file \ --enable-protocol=file \