Fix video frame duration handling

This commit is contained in:
Ali 2023-09-29 20:54:24 +04:00
parent 1b010bc17f
commit 25d8dfc800
9 changed files with 34 additions and 34 deletions

View File

@ -10,6 +10,9 @@ objc_library(
hdrs = glob([ hdrs = glob([
"Public/**/*.h", "Public/**/*.h",
]), ]),
copts = [
"-Werror",
],
includes = [ includes = [
"Public", "Public",
], ],

View File

@ -3,14 +3,14 @@
#import "libavcodec/avcodec.h" #import "libavcodec/avcodec.h"
@interface FFMpegAVCodec () { @interface FFMpegAVCodec () {
AVCodec *_impl; AVCodec const *_impl;
} }
@end @end
@implementation FFMpegAVCodec @implementation FFMpegAVCodec
- (instancetype)initWithImpl:(AVCodec *)impl { - (instancetype)initWithImpl:(AVCodec const *)impl {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {
_impl = impl; _impl = impl;
@ -19,7 +19,7 @@
} }
+ (FFMpegAVCodec * _Nullable)findForId:(int)codecId { + (FFMpegAVCodec * _Nullable)findForId:(int)codecId {
AVCodec *codec = avcodec_find_decoder(codecId); AVCodec const *codec = avcodec_find_decoder(codecId);
if (codec) { if (codec) {
return [[FFMpegAVCodec alloc] initWithImpl:codec]; return [[FFMpegAVCodec alloc] initWithImpl:codec];
} else { } else {
@ -28,7 +28,7 @@
} }
- (void *)impl { - (void *)impl {
return _impl; return (void *)_impl;
} }
@end @end

View File

@ -35,7 +35,7 @@
} }
- (int32_t)channels { - (int32_t)channels {
return (int32_t)_impl->channels; return (int32_t)_impl->ch_layout.nb_channels;
} }
- (int32_t)sampleRate { - (int32_t)sampleRate {

View File

@ -45,7 +45,7 @@
} }
- (int64_t)duration { - (int64_t)duration {
return _impl->pkt_duration; return _impl->duration;
} }
- (FFMpegAVFrameColorRange)colorRange { - (FFMpegAVFrameColorRange)colorRange {

View File

@ -6,7 +6,7 @@
#import "libavformat/avformat.h" #import "libavformat/avformat.h"
@interface FFMpegPacket () { @interface FFMpegPacket () {
AVPacket _impl; AVPacket *_impl;
} }
@end @end
@ -16,49 +16,49 @@
- (instancetype)init { - (instancetype)init {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {
av_init_packet(&_impl); _impl = av_packet_alloc();
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
av_packet_unref(&_impl); av_packet_free(&_impl);
} }
- (void *)impl { - (void *)impl {
return &_impl; return _impl;
} }
- (int64_t)pts { - (int64_t)pts {
if (_impl.pts == 0x8000000000000000) { if (_impl->pts == 0x8000000000000000) {
return _impl.dts; return _impl->dts;
} else { } else {
return _impl.pts; return _impl->pts;
} }
} }
- (int64_t)dts { - (int64_t)dts {
return _impl.dts; return _impl->dts;
} }
- (int64_t)duration { - (int64_t)duration {
return _impl.duration; return _impl->duration;
} }
- (int32_t)streamIndex { - (int32_t)streamIndex {
return (int32_t)_impl.stream_index; return (int32_t)_impl->stream_index;
} }
- (int32_t)size { - (int32_t)size {
return (int32_t)_impl.size; return (int32_t)_impl->size;
} }
- (uint8_t *)data { - (uint8_t *)data {
return _impl.data; return _impl->data;
} }
- (int32_t)sendToDecoder:(FFMpegAVCodecContext *)codecContext { - (int32_t)sendToDecoder:(FFMpegAVCodecContext *)codecContext {
return avcodec_send_packet((AVCodecContext *)[codecContext impl], &_impl); return avcodec_send_packet((AVCodecContext *)[codecContext impl], _impl);
} }
@end @end

View File

@ -34,18 +34,18 @@
@end @end
static int readPacketImpl(void * _Nullable opaque, uint8_t * _Nullable buffer, int length) { /*static int readPacketImpl(void * _Nullable opaque, uint8_t * _Nullable buffer, int length) {
FFMpegRemuxerContext *context = (__bridge FFMpegRemuxerContext *)opaque; FFMpegRemuxerContext *context = (__bridge FFMpegRemuxerContext *)opaque;
context->_offset += length; context->_offset += length;
printf("read %lld bytes (offset is now %lld)\n", (int64_t)length, context->_offset); printf("read %lld bytes (offset is now %lld)\n", (int64_t)length, context->_offset);
return read(context->_fd, buffer, length); return (int)read(context->_fd, buffer, length);
} }
static int writePacketImpl(void * _Nullable opaque, uint8_t * _Nullable buffer, int length) { static int writePacketImpl(void * _Nullable opaque, uint8_t * _Nullable buffer, int length) {
FFMpegRemuxerContext *context = (__bridge FFMpegRemuxerContext *)opaque; FFMpegRemuxerContext *context = (__bridge FFMpegRemuxerContext *)opaque;
context->_offset += length; context->_offset += length;
printf("write %lld bytes (offset is now %lld)\n", (int64_t)length, context->_offset); printf("write %lld bytes (offset is now %lld)\n", (int64_t)length, context->_offset);
return write(context->_fd, buffer, length); return (int)write(context->_fd, buffer, length);
} }
static int64_t seekImpl(void * _Nullable opaque, int64_t offset, int whence) { static int64_t seekImpl(void * _Nullable opaque, int64_t offset, int whence) {
@ -57,7 +57,7 @@ static int64_t seekImpl(void * _Nullable opaque, int64_t offset, int whence) {
context->_offset = offset; context->_offset = offset;
return lseek(context->_fd, offset, SEEK_SET); return lseek(context->_fd, offset, SEEK_SET);
} }
} }*/
@implementation FFMpegRemuxer @implementation FFMpegRemuxer

View File

@ -52,7 +52,9 @@
swr_free(&_context); swr_free(&_context);
_context = NULL; _context = NULL;
} }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
_context = swr_alloc_set_opts(NULL, _context = swr_alloc_set_opts(NULL,
av_get_default_channel_layout((int)_destinationChannelCount), av_get_default_channel_layout((int)_destinationChannelCount),
(enum AVSampleFormat)_destinationSampleFormat, (enum AVSampleFormat)_destinationSampleFormat,
@ -62,6 +64,7 @@
(int)_sourceSampleRate, (int)_sourceSampleRate,
0, 0,
NULL); NULL);
#pragma clang diagnostic pop
_currentSourceChannelCount = channelCount; _currentSourceChannelCount = channelCount;
_ratio = MAX(1, _destinationSampleRate / MAX(_sourceSampleRate, 1)) * MAX(1, _destinationChannelCount / channelCount) * 2; _ratio = MAX(1, _destinationSampleRate / MAX(_sourceSampleRate, 1)) * MAX(1, _destinationChannelCount / channelCount) * 2;
if (_context) { if (_context) {
@ -72,7 +75,7 @@
- (NSData * _Nullable)resample:(FFMpegAVFrame *)frame { - (NSData * _Nullable)resample:(FFMpegAVFrame *)frame {
AVFrame *frameImpl = (AVFrame *)[frame impl]; AVFrame *frameImpl = (AVFrame *)[frame impl];
int numChannels = frameImpl->channels; int numChannels = frameImpl->ch_layout.nb_channels;
if (numChannels != _currentSourceChannelCount) { if (numChannels != _currentSourceChannelCount) {
[self resetContextForChannelCount:numChannels]; [self resetContextForChannelCount:numChannels];
} }

View File

@ -65,7 +65,7 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
while true { while true {
let result = self.codecContext.receive(into: self.audioFrame) let result = self.codecContext.receive(into: self.audioFrame)
if case .success = result { if case .success = result {
if let convertedFrame = convertAudioFrame(self.audioFrame, pts: frame.pts, duration: frame.duration) { if let convertedFrame = convertAudioFrame(self.audioFrame, pts: frame.pts) {
self.delayedFrames.append(convertedFrame) self.delayedFrames.append(convertedFrame)
} }
} else { } else {
@ -121,7 +121,7 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
} }
} }
private func convertAudioFrame(_ frame: FFMpegAVFrame, pts: CMTime, duration: CMTime) -> MediaTrackFrame? { private func convertAudioFrame(_ frame: FFMpegAVFrame, pts: CMTime) -> MediaTrackFrame? {
guard let data = self.swrContext.resample(frame) else { guard let data = self.swrContext.resample(frame) else {
return nil return nil
} }
@ -135,18 +135,12 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
return nil return nil
} }
//var timingInfo = CMSampleTimingInfo(duration: duration, presentationTimeStamp: pts, decodeTimeStamp: pts)
var sampleBuffer: CMSampleBuffer? var sampleBuffer: CMSampleBuffer?
//var sampleSize = data.count
guard CMAudioSampleBufferCreateReadyWithPacketDescriptions(allocator: nil, dataBuffer: blockBuffer!, formatDescription: self.formatDescription, sampleCount: Int(data.count / 2), presentationTimeStamp: pts, packetDescriptions: nil, sampleBufferOut: &sampleBuffer) == noErr else { guard CMAudioSampleBufferCreateReadyWithPacketDescriptions(allocator: nil, dataBuffer: blockBuffer!, formatDescription: self.formatDescription, sampleCount: Int(data.count / 2), presentationTimeStamp: pts, packetDescriptions: nil, sampleBufferOut: &sampleBuffer) == noErr else {
return nil return nil
} }
/*guard CMSampleBufferCreate(allocator: nil, dataBuffer: blockBuffer, dataReady: true, makeDataReadyCallback: nil, refcon: nil, formatDescription: self.formatDescription, sampleCount: Int(frame.duration), sampleTimingEntryCount: 1, sampleTimingArray: &timingInfo, sampleSizeEntryCount: 1, sampleSizeArray: &sampleSize, sampleBufferOut: &sampleBuffer) == noErr else {
return nil
}*/
let resetDecoder = self.resetDecoderOnNextFrame let resetDecoder = self.resetDecoderOnNextFrame
self.resetDecoderOnNextFrame = false self.resetDecoderOnNextFrame = false

View File

@ -725,7 +725,7 @@ private func videoFrameFromPacket(_ packet: FFMpegPacket, videoStream: StreamCon
if frameDuration != 0 { if frameDuration != 0 {
duration = CMTimeMake(value: frameDuration * videoStream.timebase.value, timescale: videoStream.timebase.timescale) duration = CMTimeMake(value: frameDuration * videoStream.timebase.value, timescale: videoStream.timebase.timescale)
} else { } else {
duration = videoStream.fps duration = CMTimeMake(value: Int64(videoStream.fps.timescale), timescale: Int32(videoStream.fps.value))
} }
return MediaTrackDecodableFrame(type: .video, packet: packet, pts: pts, dts: dts, duration: duration) return MediaTrackDecodableFrame(type: .video, packet: packet, pts: pts, dts: dts, duration: duration)