12

AVFoundationを誘導してカスタムURLから読み取ろうとしています。カスタムURLのものは機能します。以下のコードは、ムービーファイルを使用してNSDataを作成します。

NSData* movieData = [NSData dataWithContentsOfURL:@"memory://video"];

次のコードを使用してAVAssetResourceLoaderオブジェクトを設定しました。

NSURL* url = [NSURL URLWithString:@"memory://video"];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetResourceLoader* loader = [asset resourceLoader];
[loader setDelegate:self queue:mDispatchQueue];

ディスパッチキューは同時です。

次に、ムービーから最初のフレームを抽出しようとします。

AVAssetImageGenerator* imageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
CMTime time = CMTimeMakeWithSeconds(0, 600);
NSError* error = nil;
CMTime actualTime;
CGImageRef image = [imageGen copyCGImageAtTime:time
                                    actualTime:&actualTime
                                         error:&error];
if (error) NSLog(@"%@", error);

しかし、これを実行すると、次のようになります。

2013-02-21 10:02:22.197 VideoPlayer[501:907] Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x1f863090 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1e575a90 "The operation couldn’t be completed. (OSStatus error 268451843.)", NSLocalizedFailureReason=An unknown error occurred (268451843)}

デリゲートメソッドの実装は次のとおりです。

- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
{
    NSData* data = [NSData dataWithContentsOfURL:loadingRequest.request.URL];
    [loadingRequest finishLoadingWithResponse:nil data:data redirect:nil];
    return YES;
}

さて、私の質問は、メソッドを正しく実装していますか?私がしていることが正しいかどうか誰かが知っていますか?

ありがとう。

編集:私が全体をフェッチしている映画は、シングルフレームの映画です。

4

4 に答える 4

8

このメソッドの実用的なバージョンを実装しました。理解するのにしばらく時間がかかりました。しかし、結果として得られるアプリは機能するようになりました。これは、コードが問題ないことを示しています。

私のアプリには、暗号化されていないパッケージで出荷したくないメディア ファイルが含まれています。ファイルを動的に復号化したかったのです。(一度にブロック)。

このメソッドは、コンテンツ リクエスト (プレーヤーに何をロードしているかを伝える) とデータ リクエスト (プレーヤーにデータを渡す) の両方に応答する必要があります。メソッドが初めて呼び出されるときは、常にコンテンツ リクエストがあります。次に、一連のデータ要求があります。

プレイヤーは貪欲です。常にファイル全体を要求します。あなたはそれを提供する義務はありません。ホールケーキを頼みます。あなたはそれに1つのスライスを与えることができます。

メディア プレーヤーのデータ ブロックを渡します。通常、一度に 1 MB。小さい最終ブロックを処理する特別なケースを使用します。通常、ブロックは順番に要求されます。ただし、シーケンス外のリクエストにも対応できる必要があります。

- (BOOL) resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
{
    NSURLRequest* request = loadingRequest.request; 
    AVAssetResourceLoadingDataRequest* dataRequest = loadingRequest.dataRequest;
    AVAssetResourceLoadingContentInformationRequest* contentRequest = loadingRequest.contentInformationRequest;

    //handle content request
    if (contentRequest)
    {
        NSError* attributesError;
        NSString* path = request.URL.path;
        _fileURL = request.URL;
        if (_fileHandle == nil)
        {
            _fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
        }

        // fire up the decryption here..
        // for example ... 
        if (_decryptedData == nil)
        {
            _cacheStart = 1000000000;
            _decryptedData = [NSMutableData dataWithLength:BUFFER_LENGTH+16];
            CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [sharedKey cStringUsingEncoding:NSISOLatin1StringEncoding], kCCKeySizeAES256, NULL, &cryptoRef);
        }

        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&attributesError];

        NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
        _fileSize = [fileSizeNumber longLongValue];

        //provide information about the content
        _mimeType = @"mp3";
        contentRequest.contentType = _mimeType;
        contentRequest.contentLength = _fileSize;
        contentRequest.byteRangeAccessSupported = YES;
    }

    //handle data request
    if (dataRequest)
    {
        //decrypt a block of data (can be any size you want) 
        //code omitted

        NSData* decodedData = [NSData dataWithBytes:outBuffer length:reducedLen];
       [dataRequest  respondWithData:decodedData];
    [loadingRequest finishLoading];
    }


    return YES;
}
于 2014-05-30T15:52:50.920 に答える
1

非常に似たようなことをしようとして2時間を無駄にしました。

デバイスでのみ機能し、iOS シミュレーターでは機能しないことがわかりました。

シミュレーターの AVFoundation は、ホスト Mac の AVFoundation に何らかの形で「ブリッジ」されていると思います。残念ながら、この API は OS X 10.8 では利用できません (WebCore のいくつかのコミットによると、OS X 10.9 で利用できるようになる予定です)。そのため、今のところシミュレーターでは動作しません。

于 2013-03-27T15:03:25.180 に答える
0

返すには NSURLResponse オブジェクトを作成する必要があります。あなたは戻ってきていますnil。これがないと、AVAssetResourceLoader は渡されたデータをどう処理するかわかりません (つまり、データの種類 (エラー メッセージ、jpeg など) がわかりません)。また、成功を想定する前に、実際に使用-[NSData dataWithContentsOfURL:options:error:]してエラーをチェックする必要があります。

于 2013-02-21T15:35:22.930 に答える