Ticket #11398: avfoundation_audio_fifo-v2.patch

File avfoundation_audio_fifo-v2.patch, 5.1 KB (added by drobinson, 20 months ago)

When the frame list overflows, advance the read index by half the FIFO length

  • libavdevice/avfoundation.m

    diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
    index 61dac4b713..6a0de33ce4 100644
    a b  
    8282    { AV_PIX_FMT_NONE, 0 }
    8383};
    8484
     85#define AVF_FRAME_LIST_LENGTH 4
     86
     87typedef struct
     88{
     89    size_t              write_index;
     90    size_t              read_index;
     91    CMSampleBufferRef   frames[AVF_FRAME_LIST_LENGTH];
     92} AVFFrameList;
     93
     94static void push_frame(AVFFrameList* list, CMSampleBufferRef frame)
     95{
     96    list->frames[list->write_index] = (CMSampleBufferRef)CFRetain(frame);
     97    list->write_index = (list->write_index + 1) % AVF_FRAME_LIST_LENGTH;
     98
     99    if (list->write_index == list->read_index) {
     100        for (int i = 0; i < (AVF_FRAME_LIST_LENGTH / 2); ++i) {
     101            CFRelease(list->frames[list->read_index]);
     102            list->read_index = (list->read_index + 1) % AVF_FRAME_LIST_LENGTH;
     103        }
     104    }
     105}
     106
     107static CMSampleBufferRef peek_frame(AVFFrameList* list)
     108{
     109    if (list->write_index != list->read_index)
     110        return list->frames[list->read_index];
     111   
     112    return nil;
     113}
     114
     115static void pop_frame(AVFFrameList* list)
     116{
     117    if (list->write_index != list->read_index) {
     118        CFRelease(list->frames[list->read_index]);
     119        list->read_index = (list->read_index + 1) % AVF_FRAME_LIST_LENGTH;
     120    }
     121}
     122
    85123typedef struct
    86124{
    87125    AVClass*        class;
     
    131169    AVCaptureVideoDataOutput *video_output;
    132170    AVCaptureAudioDataOutput *audio_output;
    133171    CMSampleBufferRef         current_frame;
    134     CMSampleBufferRef         current_audio_frame;
     172    AVFFrameList              audio_frames;
    135173
    136174    AVCaptureDevice          *observed_device;
    137175#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
    - (id)initWithContext:(AVFContext*)context  
    263301{
    264302    if (self = [super init]) {
    265303        _context = context;
     304        _context->audio_frames.write_index = 0;
     305        _context->audio_frames.read_index = 0;
    266306    }
    267307    return self;
    268308}
    - (void) captureOutput:(AVCaptureOutput *)captureOutput  
    273313{
    274314    lock_frames(_context);
    275315
    276     if (_context->current_audio_frame != nil) {
    277         CFRelease(_context->current_audio_frame);
    278     }
    279 
    280     _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
     316    push_frame(&_context->audio_frames, audioFrame);
    281317
    282318    unlock_frames(_context);
    283319
    static int get_audio_config(AVFormatContext *s)  
    695731
    696732    avpriv_set_pts_info(stream, 64, 1, avf_time_base);
    697733
    698     format_desc = CMSampleBufferGetFormatDescription(ctx->current_audio_frame);
     734    format_desc = CMSampleBufferGetFormatDescription(peek_frame(&ctx->audio_frames));
    699735    const AudioStreamBasicDescription *basic_desc = CMAudioFormatDescriptionGetStreamBasicDescription(format_desc);
    700736
    701737    if (!basic_desc) {
    static int get_audio_config(AVFormatContext *s)  
    743779    }
    744780
    745781    if (ctx->audio_non_interleaved) {
    746         CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
     782        CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(peek_frame(&ctx->audio_frames));
    747783        ctx->audio_buffer_size        = CMBlockBufferGetDataLength(block_buffer);
    748784        ctx->audio_buffer             = av_malloc(ctx->audio_buffer_size);
    749785        if (!ctx->audio_buffer) {
    static int get_audio_config(AVFormatContext *s)  
    753789        }
    754790    }
    755791
    756     CFRelease(ctx->current_audio_frame);
    757     ctx->current_audio_frame = nil;
     792    pop_frame(&ctx->audio_frames);
    758793
    759794    unlock_frames(ctx);
    760795
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11711206                unlock_frames(ctx);
    11721207                return status;
    11731208            }
    1174         } else if (ctx->current_audio_frame != nil) {
    1175             CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
     1209        } else if (peek_frame(&ctx->audio_frames) != nil) {
     1210            CMSampleBufferRef frame       = peek_frame(&ctx->audio_frames);
     1211            CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(frame);
    11761212            int block_buffer_size         = CMBlockBufferGetDataLength(block_buffer);
    11771213
    11781214            if (!block_buffer || !block_buffer_size) {
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11931229            CMItemCount count;
    11941230            CMSampleTimingInfo timing_info;
    11951231
    1196             if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_audio_frame, 1, &timing_info, &count) == noErr) {
     1232            if (CMSampleBufferGetOutputSampleTimingInfoArray(frame, 1, &timing_info, &count) == noErr) {
    11971233                AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
    11981234                pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
    11991235            }
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    12471283                }
    12481284            }
    12491285
    1250             CFRelease(ctx->current_audio_frame);
    1251             ctx->current_audio_frame = nil;
     1286            pop_frame(&ctx->audio_frames);
    12521287        } else {
    12531288            pkt->data = NULL;
    12541289            unlock_frames(ctx);