//
//  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
