2012-01-23 9 views
3

私はAVFoundationを使用してアセットをファイルに書き出すためのライブラリを作成しています。私は読者、作家を作成し、入力と出力をこれらに接続してから、入力のrequestMediaDataWhenReadyOnQueueメソッドを呼び出してデータを取得し始めます。この方法に供給されたブロックのコールバックは、ビットのようになります。[AVAssetWriterInput requestMediaDataWhenReadyOnQueue:usingBlock:]のメモリの問題

[input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{ 
    while ([input isReadyForMoreMediaData]) { 
     CMSampleBufferRef buffer; 
     // The track has some more data for us 
     if ([reader status] == AVAssetReaderStatusReading 
       && (buffer = [output copyNextSampleBuffer])) { 
      BOOL result = [input appendSampleBuffer:buffer]; 
      CFRelease(buffer); 
      if (!result) { 
       // handle error 
       break; 
      } 
     // The track is finished, for whatever reason 
     } else { 
      [input markAsFinished]; ⬅ 
      switch ([reader status]) { 
       // inspect the status and act accordingly 
      } 
     } 
    } 
}]; 

これは、iOS 5に完璧に動作しますが、iOSの4上のコードでは、⬅矢印でマークされた行の後EXC_BAD_ACCESSから死にます。いくつかのポンキングの後、私はブロックが何らかの形で完了したとして入力をマークした直後に破壊されたように感じる。悪い行を実行する前に完全に有効なselfポインタは、どういうわけか0xfff…またはデバッガによって報告されたガベージ値に変わります。しかし、ゾンビツールで確認されているように、前に指し示されたオブジェクトは問題ありません。割り当て解除されません。

私には何が欠けていますか?

+0

+1を使用してください! ʘ‿ʘ –

+0

この問題を解決できましたか? – Tonton

答えて

1

同じ(同様の)問題があります。 iOS5幸せ、iOS4.3.5、満足していない。あなたが最終的に見つけるものを学ぶことに興味があります。

writer、writer input、reader、readerの出力をrequestMedatWhenReadyOnQueueブロックの前に明示的に保持し、else節の最後に明示的に4つすべてを明示的に解放することで、

文書では、マーキングが完了した後、「ブロックは終了します。」と表示されます。たぶん彼らは冗談ではないでしょう。終了以外の操作を行うと、エラーになります。上記の回避策はうまくいくようです。

更新:資産オブジェクトをすべて保持してから解放した後でも時々クラッシュすることがありました。あなたの質問に従うと、ブロック自体が割り当て解除されているかのように、ライターの入力を完了したとマークした直後にクラッシュします。機能の一部としてブロックを渡すだけではありません。私は長寿命のオブジェクトの一部であるコピーされたブロックプロパティを作成します。私はそれをBlock_copyで初期化し、それを長命オブジェクトのデストラクタで解放します。これはトリックを行うようだ。私は以来4.3.5のクラッシュは見ていない。

+0

このソリューションのコードを投稿できますか?同じ問題があります。 – nh32rg

0

ブロックの最初の行に[self retain]を、最後の行に[self release]を試してください。

もう1つの重大な問題は、アプリケーションが一時停止(バックグラウンドで入力)した場合、アプリケーションが再起動したときに失敗するため、すべての[リーダーステータス]値を明示的にカバーする必要があることです。場合によっては、ブロックが失敗ステータスフラグで複数回実行されていたことがわかりました。同様のコードを持つ他の投稿には、AV変数の保持が多くあり、AV変数はブロックの最後にリリースされます。ブロックが複数回実行できるため、このアプローチは、アプリがバックグラウンド状態になる場合には機能しません。

私は、次の「スイッチ」(上記)でうまく動作することが分かっ:「自己」以外の

   case AVAssetReaderStatusReading: 
        break; 

       case AVAssetReaderStatusCompleted: 
        [videoWriterInput markAsFinished]; 
        //do something else, like add an audio stream 
        [videoWriter finishWriting]; 
        break; 

       case AVAssetReaderStatusFailed: 
        [videoWriterInput markAsFinished]; 
        [videoWriter finishWriting]; 
        break; 

       case AVAssetReaderStatusCancelled: 
       case AVAssetReaderStatusUnknown: 
        [videoWriterInput markAsFinished]; 
        [videoWriter cancelWriting]; 
        break; 
      } 

      dispatch_sync(dispatch_get_main_queue(), ^{ 
       //hide any progress indicators 
      }); 

      break; 

、何が保持されません。必要であれば、ブロックは自動的に変数を保持する必要があります。