123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- //
- // M4aToPcmHelper.m
- // TianyiProSwift
- //
- // Created by i2国际私塾 on 2017/3/21.
- // Copyright © 2017年 Chengdu Aitu Education Technology Ltd. All rights reserved.
- //
- #import "Mp4ToPcmHelper.h"
- #import "M4aToPcmHelper.h"
- #import <AudioToolbox/AudioToolbox.h>
- #import <AVFoundation/AVFoundation.h>
- #import <MediaPlayer/MediaPlayer.h>
- @implementation Mp4ToPcmHelper
- + (void)Mp4ToPcmWithUrl:(NSURL*)videoUrl completion:(void(^)(NSData*data))completionHandle
- {
- NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
- NSString *exportPath = [documentsDirectoryPath stringByAppendingPathComponent:@"pcmData.pcm"];
- if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
- [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
- }
- NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
-
- AVURLAsset* videoAsset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
- [videoAsset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{
- NSError *error = nil;
- AVKeyValueStatus status = [videoAsset statusOfValueForKey:@"tracks"error:&error];
- if(status == AVKeyValueStatusLoaded) { //数据加载完成
- NSError *assetError = nil;
- AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:videoAsset error:&assetError];
- if (assetError) {
- completionHandle(nil);
- return;
- }
-
- NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary];
- [outputSettings setObject:@(kCVPixelFormatType_32BGRA) forKey:(id)kCVPixelBufferPixelFormatTypeKey];
-
- NSArray *audioTracks = [videoAsset tracksWithMediaType:AVMediaTypeAudio];
- AVAssetReaderTrackOutput *readerAudioTrackOutput = nil;
- if ([audioTracks count] > 0)
- {
- AVAssetTrack* audioTrack = [audioTracks objectAtIndex:0];
- NSDictionary *outputSettings = @{AVFormatIDKey:@(kAudioFormatLinearPCM),
- AVLinearPCMIsBigEndianKey:@NO,
- AVLinearPCMIsFloatKey:@NO,
- AVLinearPCMBitDepthKey :@(16)
- };
- readerAudioTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings: outputSettings];
- readerAudioTrackOutput.alwaysCopiesSampleData = NO;
- [assetReader addOutput:readerAudioTrackOutput];
- }
-
- AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL fileType:AVFileTypeCoreAudioFormat error:&assetError];
- if (assetError) {
- completionHandle(nil);
- return;
- }
-
- AudioChannelLayout channelLayout;
- memset(&channelLayout, 0, sizeof(AudioChannelLayout));
- channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
- NSDictionary *outputSettings2 = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
- [NSNumber numberWithFloat:8000.0], AVSampleRateKey,
- [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
- [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
- [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
- [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
- [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
- [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
- nil];
- AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:outputSettings2];
- if ([assetWriter canAddInput:assetWriterInput]) {
- [assetWriter addInput:assetWriterInput];
- } else {
- completionHandle(nil);
- return;
- }
- assetWriterInput.expectsMediaDataInRealTime = NO;
- if ([assetReader startReading] == NO){
- completionHandle(nil);
- return;
- }
-
- [assetWriter startWriting];
-
- AVAssetTrack *soundTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
- CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
- [assetWriter startSessionAtSourceTime: startTime];
-
- __block UInt64 convertedByteCount = 0;
-
- while (assetWriterInput.readyForMoreMediaData) {
- CMSampleBufferRef nextBuffer = [readerAudioTrackOutput copyNextSampleBuffer];
- if (nextBuffer) {
- // append buffer
- [assetWriterInput appendSampleBuffer: nextBuffer];
- convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
- } else {
- // done!
- [assetWriterInput markAsFinished];
- [assetWriter finishWritingWithCompletionHandler:^{
- }];
- [assetReader cancelReading];
- completionHandle([NSData dataWithContentsOfURL:exportURL]);
- return;
- break;
- }
- }
- completionHandle(nil);
- return;
- }}
- ];
- }
- @end
|