Ticket #9502: use-audio-converter.patch

File use-audio-converter.patch, 12.2 KB (added by toots, 5 years ago)

Use AudioConverter API

  • libavdevice/avfoundation.m

    commit 4ac102a7e2335bfe09ab96da1b2be018a119c299
    Author: Romain Beauxis <toots@rastageeks.org>
    Date:   Mon Nov 15 11:49:14 2021 +0100
    
        Fix audio
    
    diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
    index 0cd6e646d5..194080555d 100644
    a b  
    111111
    112112    int             num_video_devices;
    113113
    114     int             audio_channels;
    115     int             audio_bits_per_sample;
    116     int             audio_float;
    117     int             audio_be;
    118     int             audio_signed_integer;
    119     int             audio_packed;
    120     int             audio_non_interleaved;
    121 
    122     int32_t         *audio_buffer;
    123     int             audio_buffer_size;
     114    AudioConverterRef audio_converter;
    124115
    125116    enum AVPixelFormat pixel_format;
    126117
    static void destroy_context(AVFContext* ctx)  
    299290    ctx->avf_delegate    = NULL;
    300291    ctx->avf_audio_delegate = NULL;
    301292
    302     av_freep(&ctx->audio_buffer);
     293    if (ctx->audio_converter) {
     294      AudioConverterDispose(ctx->audio_converter);
     295      ctx->audio_converter = NULL;
     296    }
    303297
    304298    pthread_mutex_destroy(&ctx->frame_lock);
    305299
    static int get_audio_config(AVFormatContext *s)  
    673667    AVFContext *ctx = (AVFContext*)s->priv_data;
    674668    CMFormatDescriptionRef format_desc;
    675669    AVStream* stream = avformat_new_stream(s, NULL);
     670    AudioStreamBasicDescription output_format;
     671    int audio_bits_per_sample, audio_float, audio_be;
     672    int audio_signed_integer, audio_packed, audio_non_interleaved;
     673    int must_convert = 0;
    676674
    677675    if (!stream) {
    678676        return 1;
    static int get_audio_config(AVFormatContext *s)  
    703701    stream->codecpar->channels       = basic_desc->mChannelsPerFrame;
    704702    stream->codecpar->channel_layout = av_get_default_channel_layout(stream->codecpar->channels);
    705703
    706     ctx->audio_channels        = basic_desc->mChannelsPerFrame;
    707     ctx->audio_bits_per_sample = basic_desc->mBitsPerChannel;
    708     ctx->audio_float           = basic_desc->mFormatFlags & kAudioFormatFlagIsFloat;
    709     ctx->audio_be              = basic_desc->mFormatFlags & kAudioFormatFlagIsBigEndian;
    710     ctx->audio_signed_integer  = basic_desc->mFormatFlags & kAudioFormatFlagIsSignedInteger;
    711     ctx->audio_packed          = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
    712     ctx->audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
     704    audio_bits_per_sample = basic_desc->mBitsPerChannel;
     705    audio_float           = basic_desc->mFormatFlags & kAudioFormatFlagIsFloat;
     706    audio_be              = basic_desc->mFormatFlags & kAudioFormatFlagIsBigEndian;
     707    audio_signed_integer  = basic_desc->mFormatFlags & kAudioFormatFlagIsSignedInteger;
     708    audio_packed          = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
     709    audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
     710
     711    if (audio_non_interleaved || !audio_packed) {
     712      must_convert = 1;
     713    }
     714
     715    output_format.mBitsPerChannel   = basic_desc->mBitsPerChannel;
     716    output_format.mBytesPerFrame    = basic_desc->mBytesPerFrame;
     717    output_format.mBytesPerPacket   = basic_desc->mBytesPerPacket;
     718    output_format.mChannelsPerFrame = basic_desc->mChannelsPerFrame;
     719    output_format.mFormatFlags      = kAudioFormatFlagIsPacked | audio_be;
     720    output_format.mFormatID         = kAudioFormatLinearPCM;
     721    output_format.mFramesPerPacket  = 1;
     722    output_format.mReserved         = 0;
     723    output_format.mSampleRate       = basic_desc->mSampleRate;
    713724
    714725    if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
    715         ctx->audio_float &&
    716         ctx->audio_bits_per_sample == 32 &&
    717         ctx->audio_packed) {
    718         stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
     726        audio_float &&
     727        audio_bits_per_sample == 64) {
     728        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
     729        output_format.mFormatFlags |= kAudioFormatFlagIsFloat;
     730    } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
     731        audio_float &&
     732        audio_bits_per_sample == 32) {
     733        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
     734        output_format.mFormatFlags |= kAudioFormatFlagIsFloat;
    719735    } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
    720         ctx->audio_signed_integer &&
    721         ctx->audio_bits_per_sample == 16 &&
    722         ctx->audio_packed) {
    723         stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
     736        audio_signed_integer &&
     737        audio_bits_per_sample == 16) {
     738        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
     739        output_format.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
    724740    } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
    725         ctx->audio_signed_integer &&
    726         ctx->audio_bits_per_sample == 24 &&
    727         ctx->audio_packed) {
    728         stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
     741        audio_signed_integer &&
     742        audio_bits_per_sample == 24) {
     743        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
     744        output_format.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
    729745    } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
    730         ctx->audio_signed_integer &&
    731         ctx->audio_bits_per_sample == 32 &&
    732         ctx->audio_packed) {
    733         stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
     746        audio_signed_integer &&
     747        audio_bits_per_sample == 32) {
     748        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
     749        output_format.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
     750    } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
     751        audio_signed_integer &&
     752        audio_bits_per_sample == 64) {
     753        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE;
     754        output_format.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
    734755    } else {
    735         unlock_frames(ctx);
    736         av_log(s, AV_LOG_ERROR, "audio format is not supported\n");
    737         return 1;
     756        stream->codecpar->codec_id = audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
     757        output_format.mBitsPerChannel = 32;
     758        output_format.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
     759        must_convert = 1;
    738760    }
    739761
    740     if (ctx->audio_non_interleaved) {
    741         CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
    742         ctx->audio_buffer_size        = CMBlockBufferGetDataLength(block_buffer);
    743         ctx->audio_buffer             = av_malloc(ctx->audio_buffer_size);
    744         if (!ctx->audio_buffer) {
    745             unlock_frames(ctx);
    746             av_log(s, AV_LOG_ERROR, "error allocating audio buffer\n");
     762    if (must_convert) {
     763        OSStatus ret = AudioConverterNew(basic_desc, &output_format, &ctx->audio_converter);
     764        if (ret != 0) {
     765            av_log(s, AV_LOG_ERROR, "Error while allocating audio converter\n");
    747766            return 1;
    748767        }
    749768    }
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11041123                return status;
    11051124            }
    11061125        } else if (ctx->current_audio_frame != nil) {
     1126            OSStatus ret;
    11071127            CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
    1108             int block_buffer_size         = CMBlockBufferGetDataLength(block_buffer);
     1128            size_t block_buffer_size, total_size;
     1129            char *block_buffer_data;
    11091130
    1110             if (!block_buffer || !block_buffer_size) {
    1111                 unlock_frames(ctx);
     1131            ret = CMBlockBufferGetDataPointer(block_buffer, 0, &block_buffer_size, &total_size, &block_buffer_data);
     1132
     1133            if (ret != noErr) {
    11121134                return AVERROR(EIO);
    11131135            }
    11141136
    1115             if (ctx->audio_non_interleaved && block_buffer_size > ctx->audio_buffer_size) {
    1116                 unlock_frames(ctx);
    1117                 return AVERROR_BUFFER_TOO_SMALL;
    1118             }
     1137            if (ctx->audio_converter) {
     1138                int output_size = block_buffer_size;
     1139                UInt32 size = sizeof(output_size);
     1140                ret = AudioConverterGetProperty(ctx->audio_converter, kAudioConverterPropertyCalculateOutputBufferSize, &size, &output_size);
     1141                if (ret != noErr) {
     1142                    return AVERROR(EIO);
     1143                }
    11191144
    1120             if (av_new_packet(pkt, block_buffer_size) < 0) {
    1121                 unlock_frames(ctx);
    1122                 return AVERROR(EIO);
     1145                if (av_new_packet(pkt, output_size) < 0) {
     1146                    return AVERROR(EIO);
     1147                }
     1148
     1149                ret = AudioConverterConvertBuffer(ctx->audio_converter, block_buffer_size, block_buffer_data, &pkt->size, pkt->data);
     1150
     1151                if (ret != noErr) {
     1152                    return AVERROR(EIO);
     1153                }
     1154            } else {
     1155                if (av_new_packet(pkt, block_buffer_size) < 0) {
     1156                    return AVERROR(EIO);
     1157                }
     1158
     1159                memcpy(pkt->data, block_buffer_data, pkt->size);
    11231160            }
    11241161
    11251162            CMItemCount count;
    static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)  
    11331170            pkt->stream_index  = ctx->audio_stream_index;
    11341171            pkt->flags        |= AV_PKT_FLAG_KEY;
    11351172
    1136             if (ctx->audio_non_interleaved) {
    1137                 int sample, c, shift, num_samples;
    1138 
    1139                 OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, ctx->audio_buffer);
    1140                 if (ret != kCMBlockBufferNoErr) {
    1141                     unlock_frames(ctx);
    1142                     return AVERROR(EIO);
    1143                 }
    1144 
    1145                 num_samples = pkt->size / (ctx->audio_channels * (ctx->audio_bits_per_sample >> 3));
    1146 
    1147                 // transform decoded frame into output format
    1148                 #define INTERLEAVE_OUTPUT(bps)                                         \
    1149                 {                                                                      \
    1150                     int##bps##_t **src;                                                \
    1151                     int##bps##_t *dest;                                                \
    1152                     src = av_malloc(ctx->audio_channels * sizeof(int##bps##_t*));      \
    1153                     if (!src) {                                                        \
    1154                         unlock_frames(ctx);                                            \
    1155                         return AVERROR(EIO);                                           \
    1156                     }                                                                  \
    1157                                                                                        \
    1158                     for (c = 0; c < ctx->audio_channels; c++) {                        \
    1159                         src[c] = ((int##bps##_t*)ctx->audio_buffer) + c * num_samples; \
    1160                     }                                                                  \
    1161                     dest  = (int##bps##_t*)pkt->data;                                  \
    1162                     shift = bps - ctx->audio_bits_per_sample;                          \
    1163                     for (sample = 0; sample < num_samples; sample++)                   \
    1164                         for (c = 0; c < ctx->audio_channels; c++)                      \
    1165                             *dest++ = src[c][sample] << shift;                         \
    1166                     av_freep(&src);                                                    \
    1167                 }
    1168 
    1169                 if (ctx->audio_bits_per_sample <= 16) {
    1170                     INTERLEAVE_OUTPUT(16)
    1171                 } else {
    1172                     INTERLEAVE_OUTPUT(32)
    1173                 }
    1174             } else {
    1175                 OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
    1176                 if (ret != kCMBlockBufferNoErr) {
    1177                     unlock_frames(ctx);
    1178                     return AVERROR(EIO);
    1179                 }
    1180             }
    1181 
    11821173            CFRelease(ctx->current_audio_frame);
    11831174            ctx->current_audio_frame = nil;
    11841175        } else {