Ticket #11398: avfoundation_audio_fifo.patch

File avfoundation_audio_fifo.patch, 5.0 KB (added by drobinson, 20 months ago)
  • libavdevice/avfoundation.m

    diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
    index 61dac4b713..3f52afd8c9 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        CFRelease(list->frames[list->read_index]);
     101        list->read_index = (list->read_index + 1) % AVF_FRAME_LIST_LENGTH;
     102    }
     103}
     104
     105static CMSampleBufferRef peek_frame(AVFFrameList* list)
     106{
     107    if (list->write_index != list->read_index)
     108        return list->frames[list->read_index];
     109   
     110    return nil;
     111}
     112
     113static void pop_frame(AVFFrameList* list)
     114{
     115    if (list->write_index != list->read_index) {
     116        CFRelease(list->frames[list->read_index]);
     117        list->read_index = (list->read_index + 1) % AVF_FRAME_LIST_LENGTH;
     118    }
     119}
     120
    85121typedef struct
    86122{
    87123    AVClass*        class;
     
    131167    AVCaptureVideoDataOutput *video_output;
    132168    AVCaptureAudioDataOutput *audio_output;
    133169    CMSampleBufferRef         current_frame;
    134     CMSampleBufferRef         current_audio_frame;
     170    AVFFrameList              audio_frames;
    135171
    136172    AVCaptureDevice          *observed_device;
    137173#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
    - (id)initWithContext:(AVFContext*)context  
    263299{
    264300    if (self = [super init]) {
    265301        _context = context;
     302        _context->audio_frames.write_index = 0;
     303        _context->audio_frames.read_index = 0;
    266304    }
    267305    return self;
    268306}
    - (void) captureOutput:(AVCaptureOutput *)captureOutput  
    273311{
    274312    lock_frames(_context);
    275313
    276     if (_context->current_audio_frame != nil) {
    277         CFRelease(_context->current_audio_frame);
    278     }
    279 
    280     _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
     314    push_frame(&_context->audio_frames, audioFrame);
    281315
    282316    unlock_frames(_context);
    283317
    static int get_audio_config(AVFormatContext *s)  
    695729
    696730    avpriv_set_pts_info(stream, 64, 1, avf_time_base);
    697731
    698     format_desc = CMSampleBufferGetFormatDescription(ctx->current_audio_frame);
     732    format_desc = CMSampleBufferGetFormatDescription(peek_frame(&ctx->audio_frames));
    699733    const AudioStreamBasicDescription *basic_desc = CMAudioFormatDescriptionGetStreamBasicDescription(format_desc);
    700734
    701735    if (!basic_desc) {
    static int get_audio_config(AVFormatContext *s)  
    743777    }
    744778
    745779    if (ctx->audio_non_interleaved) {
    746         CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
     780        CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(peek_frame(&ctx->audio_frames));
    747781        ctx->audio_buffer_size        = CMBlockBufferGetDataLength(block_buffer);
    748782        ctx->audio_buffer             = av_malloc(ctx->audio_buffer_size);
    749783        if (!ctx->audio_buffer) {
    static int get_audio_config(AVFormatContext *s)  
    753787        }
    754788    }
    755789
    756     CFRelease(ctx->current_audio_frame);
    757     ctx->current_audio_frame = nil;
     790    pop_frame(&ctx->audio_frames);
    758791
    759792    unlock_frames(ctx);
    760793
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11711204                unlock_frames(ctx);
    11721205                return status;
    11731206            }
    1174         } else if (ctx->current_audio_frame != nil) {
    1175             CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
     1207        } else if (peek_frame(&ctx->audio_frames) != nil) {
     1208            CMSampleBufferRef frame       = peek_frame(&ctx->audio_frames);
     1209            CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(frame);
    11761210            int block_buffer_size         = CMBlockBufferGetDataLength(block_buffer);
    11771211
    11781212            if (!block_buffer || !block_buffer_size) {
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11931227            CMItemCount count;
    11941228            CMSampleTimingInfo timing_info;
    11951229
    1196             if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_audio_frame, 1, &timing_info, &count) == noErr) {
     1230            if (CMSampleBufferGetOutputSampleTimingInfoArray(frame, 1, &timing_info, &count) == noErr) {
    11971231                AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
    11981232                pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
    11991233            }
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    12471281                }
    12481282            }
    12491283
    1250             CFRelease(ctx->current_audio_frame);
    1251             ctx->current_audio_frame = nil;
     1284            pop_frame(&ctx->audio_frames);
    12521285        } else {
    12531286            pkt->data = NULL;
    12541287            unlock_frames(ctx);